所以像
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
相当于f
whenx
没有出现在 中f
。
让我们将其应用于您的案例。我猜你对像这样的定义很满意addList xs = foldl1 (+) xs
。我们可以将其重写为addList = \xs -> foldl1 (+) xs
现在应用我们得到的 eta 减少规则addList = foldl1 (+)
。
该规则基于这样的想法,即如果两个函数在应用于相同的参数时给出相同的结果,则它们是相等的。这里的两个函数是f
和g = \x -> f x
where 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