组成和功能应用之间的差异

时间:2014-04-01 18:28:25

标签: haskell

99 Haskell Problems中的第一个问题是"找到列表的最后一个元素"。我想出了两个解决方案:

解决方案1(可行)

myLast :: [a] -> a
myLast = head . reverse

解决方案2(这不起作用)

myLast :: [a] -> a
myLast = head $ reverse

问题

  • 为什么解决方案1有效但解决方案2无效?我最困惑的是如何实现供应模式匹配。

2 个答案:

答案 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 -> IntInt

答案 1 :(得分:1)

粗略地说,应用程序($)用在函数及其参数(本例中为列表)之间,而组合(.)用于两个函数之间。

关于模式匹配:在第一个解决方案中,函数reverse将为您执行所需的模式匹配,因此myLast不需要。