2015-12-12 14 views
8

Tôi nhận thấy có sự khác biệt giữa Haskell và Erlang khi nói đến foldl.Haskell vs erlang: sự khác biệt trong foldl?

Đối foldr, cả hai ngôn ngữ trả lại kết quả tương tự:

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 

Nhưng các giá trị để đổi lấy foldl là khác nhau:

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 

Làm thế nào sự khác biệt này có thể giải thích?

+3

Thứ tự của đối số cho đối số đầu tiên của 'foldl' và' foldr' có vẻ khác trong Haskell: 'foldl :: Foldable t => (b -> a -> b) -> b -> ta - > b' và 'foldr :: Có thể gập lại t => (a -> b -> b) -> b -> ta -> b'. – Dogbert

+1

'2 * x + y' so với' X + 2 * Y' - được dự định? – chi

+0

@chi Rất quan sát, hóa ra tôi đã trộn lẫn cả hai! Tuy nhiên, vấn đề vẫn còn tồn tại, ngoại trừ việc nó bây giờ là chính xác theo cách khác xung quanh ... 'foldr' cư xử như nhau, nhưng' foldl' trả về một số khác nhau. –

Trả lời

13

Bạn đang bối rối vì không đơn giản hóa chức năng nếp gấp của bạn.

lần trái, 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 

lần trái, 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 

lần đúng, 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 

lần đúng, 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 

Từ đó, thì rõ ràng rằng trong Haskell, các foldl chức năng sẽ được thông qua (Accumulator, Element) trong khi foldr chức năng sẽ được thông qua (Element, Accumulator). Mặt khác, cả hai chức năng trong Erlang sẽ được thông qua (Element, Accumulator).

Các vấn đề liên quan