Haskell Foldl с (++) - PullRequest
       19

Haskell Foldl с (++)

7 голосов
/ 26 февраля 2011

Я играл с Haskell и ghci, когда обнаружил, что меня действительно беспокоит:

foldl (++) [[3,4,5], [2,3,4], [2,1,1]] []

Я ожидал получить это: [3,4,5,2,3,4,2,1,1] Однако он получает:

[[3,4,5],[2,3,4],[2,1,1]]

Насколько я понимаю foldl, так и должно быть:

(([] ++ [3, 4, 5]) ++ [2, 3, 4]) ++ [2, 1, 1]

Если я наберу это в ghci, то это действительно будет [3,4,5,2,3,4,2,1,1].

И еще одна странная вещь заключается в следующем:

Prelude> foldl1 (++) [[3,4,5], [2, 3, 4], [2, 1, 1]]
[3,4,5,2,3,4,2,1,1]

Я ожидаю, что foldl и foldl1 будут вести себя одинаково. Так что же на самом деле делает foldl?

Ответы [ 3 ]

20 голосов
/ 26 февраля 2011

Порядок аргументов неправильный.Правильный: foldl (++) [] [[3,4,5], [2,3,4], [2,1,1]] (то есть сначала аккумулятор, затем список.)

5 голосов
/ 26 февраля 2011

Вы изменили аргументы.foldl сначала берет начальное значение аккумулятора, затем список, чтобы сложить.Так что в вашем случае foldl сгибается по пустому списку и, таким образом, возвращает начальное значение, которое [[3,4,5], [2, 3, 4], [2, 1, 1]].Это будет делать то, что вы хотите:

foldl (++) [] [[3,4,5], [2, 3, 4], [2, 1, 1]]
2 голосов
/ 26 февраля 2011

Вы неправильно указали порядок аргументов

Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldl1
foldl1 :: (a -> a -> a) -> [a] -> a

Первоначальное значение идет первым. В вашем случае ваше начальное значение было [[3,4,5],[2,3,4],[2,1,1]], и вы свернули пустой список, поэтому вы вернулись к исходному значению.

...