Как переписать фолд с анонимной функцией в Haskell в обычную функцию? - PullRequest
2 голосов
/ 07 марта 2020

Я пытаюсь научить себя функциональному программированию с использованием Haskell.

Мне трудно понять карри и лямбды.

Это функция, которая генерирует список исправлений списка (выводит список списков).

foldr (\element accumulator -> [] : map (element:) accumulator) [[]]

Я пытаюсь переписать его как обычную функцию без лямбды, чтобы помочь мне понять, как работают лямбды. Как бы я это сделал? Я застрял. Нужна ли мне вспомогательная функция? Спасибо.

Ответы [ 3 ]

4 голосов
/ 07 марта 2020

Да, вам понадобится вспомогательная функция. Пункты where - отличное место для таких помощников. where предложения прилагаются к определению , поэтому мне нужно будет назвать вашу функцию (я назвал ее inits). Начните с дословного перемещения выражения.

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper = \element accumulator -> [] : map (element:) accumulator

Затем вы можете переместить лямбда-аргументы справа к привязкам параметров слева, что означает то же самое:

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper element accumulator = [] : map (element:) accumulator

(Вы также можете просто сделать один параметр:

    helper element = \accumulator -> [] : map (element:) accumulator

Все они эквивалентны.)

2 голосов
/ 08 марта 2020

Звучит так, будто вы ищете pointfree форму. Да, это можно сделать.

inits :: [a] -> [[a]]
inits = foldr ((([]:).) . map . (:)) [[]]

Попробуйте онлайн!

Ваша лямбда превратилась в (([]:).) . map . (:). Не очень красиво, а? И намного сложнее понять. Я предлагаю вам уклоняться от этого подхода.

1 голос
/ 08 марта 2020

В общем,

foldr g [[]] []            =  [[]]
foldr g [[]] [a,b,c, ...]  =  g a (foldr g [[]] [b,c, ...]) 

Ваша функция g равна ( \ x y -> [] : map (x:) y ) т.е.

                    g x y  =  [] : map (x:) y

Таким образом, с вашим g мы имеем

foldr g [[]] [a,b,c, ...]  =  [] : map (a:) (foldr g [[]] [b,c, ...])

Заменив foldr g [[]] просто foo, а псевдокод [a,b,c, ...] действительным шаблоном (a:bc), мы получим

foo          []            =  [[]]
foo          (a:bc)        =  [] : map (a:) (foo           bc       )

, который является «обычной функцией» без лямбды и без where пункт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...