99 Haskell Problems中的第一个问题是"找到列表的最后一个元素"。我想出了两个解决方案:
解决方案1(可行)
myLast :: [a] -> a
myLast = head . reverse
解决方案2(这不起作用)
myLast :: [a] -> a
myLast = head $ reverse
问题
答案 0 :(得分:3)
head
是一个参数 1 的函数。如果您使用f $ x
将某个函数应用于某个内容,则只需编写f x
(或者如果您喜欢f(x)
或(f)x
,则完全相同)只是丑陋的):参数被指定的变量“填充”。所以head $ reverse
的结果只是head
给你的reverse
类型的参数给出的结果......但是不起作用,因为{ {1}}需要一个列表,但head
是一个函数。 reverse
本身并不关心这一点,只是提供参数,例如你可以写
前奏> :t map $ reverse
map $ reverse :: [[a]] - > [[α]]
因为$
的第一个参数实际上是一个函数。
map
与众不同。这关心它的右边的参数是什么类型(也必须是一个函数),它不会简单地将它直接提供给左边的函数。相反,(.)
会产生另一个函数,它执行以下操作:它等待一些参数f . g
,它将其提供给x
,然后提供该的结果为g
。
现在,如果你写
f
这意味着,您将myLast' = head . reverse
定义为myLast
为(.)
和head
的组合提供的此功能。这里没有为reverse
提到的参数无关紧要:myLast
只是某种类型,所以你可以通过将它们分配给碰巧有这种类型的值来定义这种类型的变量(比如myLast)函数类型(如[a] -> a
)。 可以,如果需要,可以使参数显式:
head . reverse
请注意,需要parens,否则它被解析为myLast'' x = (head . reverse) x
- 这不起作用,因为head . (reverse x)
不再是一个函数,只是一个结果列表。因此你不能用reverse x
撰写它;你可以做的是应用 head
:
head
1 事实上, Haskell中的每个函数都只有一个参数......但我们对myLast''' x = head $ reverse x
之类的东西说“双参数函数”,虽然这是一个单参数函数,返回一个参数函数返回(+) :: Int -> Int -> Int
:Int
。
答案 1 :(得分:1)
粗略地说,应用程序($
)用在函数及其参数(本例中为列表)之间,而组合(.
)用于两个函数之间。
关于模式匹配:在第一个解决方案中,函数reverse
将为您执行所需的模式匹配,因此myLast
不需要。