2015-12-12 48 views
8

Zauważyłem, że istnieje różnica między Haskell i Erlang, jeśli chodzi o foldl.Haskell vs. erlang: różnica w foldl?

Dla foldr, oba języki zwraca te same wyniki:

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 

Ale zwracane wartości dla foldl są różne:

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 

Jak można wytłumaczyć tę różnicę?

+3

Kolejność argumentów pierwszego argumentu 'foldl' i' foldr' wydaje się być inna w Haskell: 'foldl :: Foldable t => (b -> a -> b) -> b -> ta - > b' i 'foldr :: Składany t => (a -> b -> b) -> b -> ta -> b'. – Dogbert

+1

'2 * x + y' vs' X + 2 * Y' - czy to jest zamierzone? – chi

+0

@chi Bardzo spostrzegawczy, okazuje się, że pomieszałem te dwa! Jednak problem nadal istnieje, z tym wyjątkiem, że jest teraz dokładnie odwrotnie ... 'foldr' zachowuje się tak samo, ale' foldl' zwraca inną liczbę. –

Odpowiedz

13

Mylisz się, nie upraszczając funkcji składania.

krotnie lewy, 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 

krotnie lewo, 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 

krotnie rację, Haskell:

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 

krotnie rację, 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 

Z tego, to jasne, że w Haskell, funkcja foldl zostaną przekazane (Accumulator, Element) natomiast funkcja foldr zostaną przekazane (Element, Accumulator). Z drugiej strony obie funkcje w Erlangu zostaną przekazane (Element, Accumulator).