Haskell 哈斯凯尔与埃尔朗:foldl的区别?

Haskell 哈斯凯尔与埃尔朗:foldl的区别?,haskell,erlang,fold,Haskell,Erlang,Fold,我注意到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

我注意到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

如何解释这种差异呢?

你没有简化折叠功能,这让你感到困惑

向左折叠,Haskell

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
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
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
左折,二郎

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
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
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

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
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
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
右折,二郎

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
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
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
函数将被传递
(累加器,元素)
,而
foldr
函数将被传递
(元素,累加器)
。另一方面,Erlang中的两个函数都将被传递
(元素,累加器)

foldl
foldr
的第一个参数的参数顺序在Haskell中似乎是不同的:
foldl::Foldable t=>(b->a->b->ta->b
foldr::Foldable t=>(a->b)->b->TA->b
2*x+y
vs
x+2*y
——这是故意的吗?@chi观察力很强,原来我把这两种东西混在一起了!然而,问题仍然存在,只是现在正好相反
foldr
的行为相同,但是
foldl
返回一个不同的数字。这支持Dogbert的建议:Erlang
foldl(f,x,l)
似乎等同于Haskell
foldl(flip f)xl
-
f
以不同的顺序获取参数。