5

所以像

addList :: [int] -> int
addList = foldl1 (+)

为什么这行得通?咖喱部分。为什么没有变量?

4

3 回答 3

11

如果你定义一个类似的函数f x y = bla,这与 相同f x = \y -> bla,与 相同f = \x -> (\y -> bla)。换句话说f,一个函数接受一个参数 ,x然后返回另一个函数,该函数接受一个参数 ,y然后返回实际结果。这被称为柯里化。

类似地,当你这样做时f x y,它与 相同(f x) y。即你f用参数调用函数x。这将返回另一个函数,您将其应用于参数y

所以换句话说,当你这样做时addList xs = foldl1 (+) xs,你首先调用foldl1 (+)which 然后返回另一个函数,你应用到xs. 因此,由于返回的函数foldl1 (+)实际上与 相同addList,因此您可以将其缩短为addList = foldl1 (+).

于 2010-09-25T15:35:51.873 回答
5

除了柯里化,正如 sepp2k 指出的那样,这里我们使用所谓的eta reduction。它是 lambda 演算的约简规则之一,是 Haskell 的基础。它说\x -> f x相当于fwhenx没有出现在 中f

让我们将其应用于您的案例。我猜你对像这样的定义很满意addList xs = foldl1 (+) xs。我们可以将其重写为addList = \xs -> foldl1 (+) xs现在应用我们得到的 eta 减少规则addList = foldl1 (+)

该规则基于这样的想法,即如果两个函数在应用于相同的参数时给出相同的结果,则它们是相等的。这里的两个函数是fg = \x -> f xwhere f : a -> b,我们想为所有人展示c : a, f c = g c。为了证明它采用任意值c : a并将其应用于g: g c = (\x -> f x) c = f c,最后一个相等是通过另一个称为 beta 缩减的规则,它表示函数应用是通过替换来评估的。

于 2010-09-25T18:01:59.640 回答
2

sepp2k 的解释是正确的,我只想指出(双关语)这种柯里化的应用有一个名字:它被称为“无点风格”。这是一个很好的解释,包括利弊:http ://www.haskell.org/haskellwiki/Pointfree

于 2010-09-25T17:56:32.400 回答