Haskell:初学者函数语法混乱
我目前正在尝试学习Haskell,但我正在努力理解语法。例如,以Haskell:初学者函数语法混乱,haskell,Haskell,我目前正在尝试学习Haskell,但我正在努力理解语法。例如,以map函数为例: map :: (s -> t) -> [s] -> [t] map f [] = [] map f (x:xs) = f x : map f xs 我理解函数的作用,并且map有一个f::s->t函数作为参数。但是我把map:(s->t)->[s]->[t]理解为“map是一个函数,它将函数从s映射到t,然后映射到t”,这显然是错误的。有人能帮我澄清一下吗?map是一个函数,它将一个(函数从s映
map
函数为例:
map :: (s -> t) -> [s] -> [t]
map f [] = []
map f (x:xs) = f x : map f xs
我理解函数的作用,并且map
有一个f::s->t
函数作为参数。但是我把map:(s->t)->[s]->[t]理解为“map是一个函数,它将函数从s映射到t,然后映射到t”,这显然是错误的。有人能帮我澄清一下吗?map是一个函数,它将一个(函数从s映射到t)映射到一个(s列表)上,给出一个(t列表)”?
这是将类型签名直接翻译成英语(尽管不是很优雅的英语)。类型(s->t)->[s]->[t]
可以通过两种方式读取。一种方法是将其视为两个参数的函数,第一个参数是s->t
类型的函数,第二个参数是[s]
类型的列表。返回值的类型为[t]
另一种方法是理解函数箭头是右关联的,因此类型相当于(s->t)->([s]->[t])
。在这种解释下,map
是一个函数,它将一个函数从一个元素转换到另一个元素s->t
,并将其转换为一个函数从一个列表转换到另一个列表[s]->[t]
类似地,在使用函数时,可以将map foo xs
视为将函数map
应用于两个参数foo
和xs
。或者,由于函数应用程序是左关联的,您可以将其视为(map foo)xs
,将map
应用于单个参数foo
,以获取新函数,然后将其应用于xs
因为Haskell函数是,所以这只是两种看待完全相同事物的方式。从末尾读取签名:
->[t]
表示返回一个t
的列表。其余是“常规”参数
因此,map
接受一个函数,该函数从s
生成一个t
,以及一个s
列表
现在很简单:取一个函数
s->t
,将其应用于[s]
的每个元素,其结果就是[t]
定义一对类型别名可能会有帮助,使所有这些箭头和括号的作用更加明确:
type F1 a b=a->b--单参数函数的类型同义词
类型列表a=[a]--列表的类型同义词
因此,现在您可以将映射
的类型签名编写为:
map::F1 s t->List s->List t
<>,如果你更熟悉java或C++,或者任何语法,看起来语法上有点像:
列表地图(F1乐趣,列表);//将乐趣应用于列表中的每个元素
所以你可以这样想:map
接受一个函数和一个列表,然后返回另一个列表。但是,由于函数是在Haskell中实现的,因此不必一次传递所有参数。您可以仅对其第一个参数部分应用map
。所以它的类型签名更像:
F1地图(F1乐趣);//返回一个函数,该函数将乐趣应用于列表中的每个元素
。。。当你用一个fun
参数调用map
时,它会给你一些类似的东西:
List mapFun(列表);//将乐趣应用于列表中的每个元素
现在回到Haskell:您可以阅读map::(s->t)->[s]->[t]
如下:
获取一个从s到t的函数和一个s列表,并返回一个t列表map
将函数从s到t,并将其转换为从s列表到t列表的函数map
前者是好的;后者更有用。警告:如果您不熟悉Java或其他什么,最好完全忽略我的答案,除了最后一点;)同意。所有的“s”和“s”让我想到“都不,现在我理解了haskell..他们再次更改它和/或提出另一个扩展”:-)不够笼统;例如,您将如何翻译类型签名
zipWith:(a->b->c)->[a]->[b]->[c]
?术语“映射布拉赫之上布拉赫的函数”来源于您所知道的映射,而不是它的类型签名。对于zipWith
示例,我认为它“将函数从a和b转换为c,并将其从a列表和b列表转换为c列表中的新函数。”