所以像
addList :: [int] -> int
addList = foldl1 (+)
为什么这行得通?咖喱部分。为什么没有变量?
所以像
addList :: [int] -> int
addList = foldl1 (+)
为什么这行得通?咖喱部分。为什么没有变量?
如果你定义一个类似的函数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 (+).
除了柯里化,正如 sepp2k 指出的那样,这里我们使用所谓的eta reduction。它是 lambda 演算的约简规则之一,是 Haskell 的基础。它说\x -> f x相当于fwhenx没有出现在 中f。
让我们将其应用于您的案例。我猜你对像这样的定义很满意addList xs = foldl1 (+) xs。我们可以将其重写为addList = \xs -> foldl1 (+) xs现在应用我们得到的 eta 减少规则addList = foldl1 (+)。
该规则基于这样的想法,即如果两个函数在应用于相同的参数时给出相同的结果,则它们是相等的。这里的两个函数是f和g = \x -> f xwhere f : a -> b,我们想为所有人展示c : a, f c = g c。为了证明它采用任意值c : a并将其应用于g: g c = (\x -> f x) c = f c,最后一个相等是通过另一个称为 beta 缩减的规则,它表示函数应用是通过替换来评估的。
sepp2k 的解释是正确的,我只想指出(双关语)这种柯里化的应用有一个名字:它被称为“无点风格”。这是一个很好的解释,包括利弊:http ://www.haskell.org/haskellwiki/Pointfree