我注意到Haskell和Erlang之间存在差异foldl
.
因为foldr
,两种语言都返回相同的结果:
foldr (\x y -> 2*x+y) 4 [1, 2, 3] -- returns 49 lists:foldr(fun(X, Y) ?> X+2?Y end, 4, [1,2,3]). % returns 49
但是返回值foldl
是不同的:
foldl (\x y -> x+2*y) 4 [1, 2, 3] -- returns 16 lists:foldl(fun(X, Y) ?> X+2?Y end, 4, [1,2,3]). -- returns 43
如何解释这种差异?
你不会因为不简化你的折叠功能而让自己感到困惑.
向左折,哈斯克尔:
Prelude Debug.Trace> foldl (\x y -> trace("x:"++show x++" y:"++show y) $ x+y) 4 [1,2,3] x:4 y:1 x:5 y:2 x:7 y:3 10
弃左,Erlang:
1> lists:foldl(fun (X,Y) -> io:format("x:~p y:~p~n", [X,Y]), X+Y end, 4, [1,2,3]). x:1 y:4 x:2 y:5 x:3 y:7 10
向右折,哈斯克尔:
Prelude Debug.Trace> foldr (\x y -> trace("x:"++show x++" y:"++show y) $ x+y) 4 [1,2,3] x:3 y:4 x:2 y:7 x:1 y:9 10
向右折,Erlang:
2> lists:foldr(fun (X,Y) -> io:format("x:~p y:~p~n", [X,Y]), X+Y end, 4, [1,2,3]). x:3 y:4 x:2 y:7 x:1 y:9 10
由此可见,在Haskell中,foldl
函数将在函数传递(Accumulator, Element)
时foldr
传递(Element, Accumulator)
.另一方面,Erlang中的两个函数都将被传递(Element, Accumulator)
.