Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “什么是”呢;起重“;在哈斯克尔?_Haskell_Functional Programming - Fatal编程技术网

Haskell “什么是”呢;起重“;在哈斯克尔?

Haskell “什么是”呢;起重“;在哈斯克尔?,haskell,functional-programming,Haskell,Functional Programming,我不明白什么是“提升”。在理解“提升”是什么之前,我应该先理解单子吗?(我也完全不知道单子:)或者有人能用简单的话给我解释一下吗?提升是一个概念,它允许您在另一个(通常更一般)设置中将一个函数转换为相应的函数 看一看让我们从一个例子开始(为了更清晰地表达,添加了一些空白): liftA2将普通类型的函数转换为封装在应用程序中的相同类型的函数,例如列表、IO等 另一种常见的提升方式是Control.Monad.Trans中的lift。它将一个单子的一元动作转换为一个已转换单子的动作 通常,“lif

我不明白什么是“提升”。在理解“提升”是什么之前,我应该先理解单子吗?(我也完全不知道单子:)或者有人能用简单的话给我解释一下吗?

提升是一个概念,它允许您在另一个(通常更一般)设置中将一个函数转换为相应的函数


看一看

让我们从一个例子开始(为了更清晰地表达,添加了一些空白):

liftA2
将普通类型的函数转换为封装在
应用程序中的相同类型的函数,例如列表、
IO

另一种常见的提升方式是
Control.Monad.Trans
中的
lift
。它将一个单子的一元动作转换为一个已转换单子的动作

通常,“lift”将函数/动作提升为“wrapped”类型(因此原始函数在“wrapped”下工作)


要理解这一点,以及单子等,并理解它们为什么有用,最好的方法可能是编码并使用它。如果您之前编写的代码中有任何内容可能会从中受益(即,这将使代码更短,等等),那么您只需尝试一下,就可以轻松掌握概念。

提升更多地是一种设计模式,而不是一个数学概念(尽管我希望这里的人现在会反驳我,说明电梯是一个什么样的类别)

通常,您有一些带有参数的数据类型

data Foo a = Foo { ...stuff here ...}
假设您发现
Foo
的许多用法都采用数字类型(
Int
Double
等),并且您必须不断编写代码,将这些数字展开、相加或相乘,然后将其重新包装。您可以通过编写一次展开和包装代码来缩短此过程。此函数传统上称为“提升”,因为它看起来像这样:

liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
import Control.Applicative

instance Applicative Foo where
   pure x = Foo $ ...   -- Wrap 'x' inside a Foo.
   (<*>) = liftFoo2 ($)
换句话说,您有一个函数,它接受一个双参数函数(如
(+)
运算符),并将其转换为Foos的等效函数

现在你可以写了

addFoo = liftFoo2 (+)
编辑:更多信息

当然,您可以使用
liftFoo3
liftFoo4
等等。但是这通常不是必需的

从观察开始

liftFoo1 :: (a -> b) -> Foo a -> Foo b
但这与
fmap
完全相同。因此,您不必编写
liftFoo1

instance Functor Foo where
   fmap f foo = ...
如果你真的想要完全的规律性,你可以说

liftFoo1 = fmap
如果你能把
Foo
变成一个函子,也许你能把它变成一个应用函子。事实上,如果你能写
liftFoo2
,那么应用实例如下所示:

liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
import Control.Applicative

instance Applicative Foo where
   pure x = Foo $ ...   -- Wrap 'x' inside a Foo.
   (<*>) = liftFoo2 ($)
同样,还有
liftA
liftA3
,但实际上您并不经常使用它们,因为还有另一个操作符

(<$>) = fmap
()=fmap
这使您可以编写:

result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
result=myFunction arg1 arg2 arg3 arg4

术语
myFunction arg1
返回一个用Foo包装的新函数。这反过来可以应用于下一个参数,使用
()
,依此类推。因此,现在不是每个算术都有一个提升函数,而是有一个菊花链应用程序。

Paul和yairchu都是很好的解释

我想补充一点,被提升的函数可以有任意数量的参数,并且它们不必是相同的类型。例如,您还可以定义一个liftFoo1:

liftFoo1 :: (a -> b) -> Foo a -> Foo b
通常,在类型类
Functor
中捕获带1个参数的函数的提升,提升操作称为
fmap

fmap :: Functor f => (a -> b) -> f a -> f b
注意与
liftFoo1
类型的相似性。事实上,如果您有
liftFoo1
,则可以将
Foo
作为
Functor
的实例:

instance Functor Foo where
  fmap = liftFoo1
此外,将提升推广到任意数量的参数被称为应用程序风格。在掌握具有固定数量参数的函数提升之前,不要费心深入研究这个问题。但是,当你掌握了提升时,有一个很好的章节介绍了这一点。这是描述函子和应用程序的另一个很好的文档(以及其他类型类;向下滚动到文档中的右侧章节)


希望这有帮助!

根据,函子是某种容器(如
可能
列表
,可以存储另一种类型的元素,
a
).我使用Java泛型表示法,
表示元素类型
a
,并将元素视为树
上的浆果。有一个函数
fmap
,它采用元素转换函数
a->b
和容器
functor
。它将
a->b
应用于contai的每个元素当只提供第一个参数时,
a->b
fmap
等待
函子
。也就是说,仅提供
a->b
就将此元素级函数转换为在容器上运行的函数
函子
。这称为提升因为容器也称为函子,所以提升的先决条件是函子而不是单子。单子有点“并行”“到提升。两者都依赖于函子的概念,并且都做
f->f
。区别在于提升使用
a->b
进行转换,而Monad要求用户定义
a->f

可能有用,可能没有:是的,但页面开头是“我们通常从一个(协变)函子开始…”。不完全是新手友好。但是“functor”是链接的,所以新手只需点击它就可以看到functor是什么。无可否认,链接页面不太好。我需要获得一个帐户并解决这个问题。这是我在其他函数编程网站上看到的一个问题;每个概念都会用其他(不熟悉的)概念来解释,直到新手绕了一整圈(绕了一圈)穆先生
instance Functor Foo where
  fmap = liftFoo1