2016-06-06 4 views
3

Может ли кто-нибудь объяснить, как работает foldl?
Я понял, что, например, foldr (-) 0 [1,2,3] производит (1 - (2 - (3 - 0))), тогда как foldl (-) 0 [1,2,3] производит (((0 - 1) - 2) - 3), но у меня есть еще несколько вопросов:Как работает складной склад?

  • первым примером (длина списка с foldr/foldl):
    foldr (\_ acc -> acc + 1) 0 [1,2,3,4,5] производит 5, как ожидалось.
    foldl (\_ acc -> acc + 1) 0 [1,2,3,4,5] производит 6.: |
    foldl (\_ acc -> acc + 1) 0 [2] производит 3.: |
    Как реагировать на эти приведенные примеры?

  • второй пример:
    foldr (:) [] [1,2,3,4] производит [1,2,3,4] - не переживайте, но foldl (:) [] [1,2,3,4] дает мне ошибку: Occurs check: cannot construct the infinite type: a ~ [a]
    Что случилось с foldl?

+8

Для 'foldl' вам нужно переключить порядок аргументов между' acc' и '_', потому что' foldr' логически помещает начальный аргумент в конец последовательности, а 'foldl' логически помещает его в начале. Это означает, что аккумулятор является первым (!) Аргументом функции сгибания для 'foldl' (и второго аргумента для' foldr'). Из-за этой ошибки ваш аккумулятор «начинает» на '1' для' foldl', а не '0'. Если вы измените список на '[" a "," b "," c "," d "," e "]', например, вы получите хорошую ошибку проверки типа в образце 'foldl'. – MicroVirus

+3

Если вы попробуете 'foldl (\ _ acc -> acc + 1) 0 [0,0,0,0]', то, возможно, вы увидите свою ошибку. – pdexter

+0

Спасибо, @MicroVirus! – pkenobi23

ответ

4

В foldr, аккумулятор является вторым аргументом функции вы складной с, но в foldl, аккумулятор является первым аргументом. Если вы внимательно посмотрите на вводный параграф вопроса, вы можете это решить самостоятельно ...

Код «1-й пример» вводит в заблуждение, поскольку аргумент acc (название которого предполагает, что он должен быть аккумулятором) является последовательно второй аргумент лямбда, когда он должен быть первым для foldl. Это также запутывает, потому что тип и значения элементов списка образцов отражают тип и значение значения аккумулятора ... как отмечают комментарии, было бы лучше использовать другие значения и еще лучше использовать какой-либо другой тип!

Для «второго примера» вы получаете ошибку типа, потому что ваши аргументы меняются местами (и вы не можете иметь список, элементы которого являются списками самого себя). Либо поменять порядок аргументов вручную:

foldl (\xs x -> x:xs) 

или другое использование flip, функция библиотеки, предназначенную для этого:

foldl (flip (:)) 

Обратите внимание, что результат для foldl случае должен быть перевернутым список (а не скопирован один), потому что foldl выполняет итерацию в противоположном направлении от foldr.

 Смежные вопросы

  • Нет связанных вопросов^_^