карта по сравнению с mapM поведением

Я нахожусь на главе ввода-вывода Реального мира Haskell. Монады не обсуждены в книге еще для 7 глав. Который должен сказать, мое понимание ввода-вывода, в лучшем случае неполно.

Прямо сейчас я пытаюсь постигать функцию mapM. Насколько я понимаю функция "выполняет" каждый элемент в списке, который должен быть "действием" (монада IO).

То, что не имеет смысла, является этим примером. Почему mapM возвращает другой результат, чем карта для тех же аргументов?

Prelude> map (\x -> [x]) [0, 1, 2]
[[0],[1],[2]]
Prelude> mapM (\x -> [x]) [0, 1, 2]
[[0,1,2]]

31
задан Guy Coder 15 December 2013 в 14:28
поделиться

2 ответа

Насколько я понимаю, функция «выполняет» каждый элемент в списке, который должен быть «действием» (монада ввода-вывода ).

Это верно для ввода-вывода, но в вашем примере кода вы не используете монаду ввода-вывода, вы используете монаду списка (функция, которую вы передаете mapM, возвращает список ( [x] ), а не IO).

mapM определяется как mapM f as = sequence (map f as) . Если f возвращает IO, это означает, что для каждого элемента в списке он создает IO, применяя f к элементу. Затем он превращает список операций ввода-вывода, возвращаемых картой, в ввод-вывод, «содержащий» список с использованием последовательности (поэтому, когда вы выполняете ввод-вывод, вы получаете обратно список, содержащий значения, не относящиеся к вводу-выводу).

Для списков это означает, что он создает список списков, применяя f к каждому элементу как . Затем он использует последовательность для создания списка списков, который содержит все возможные способы взять один элемент каждого списка в списках списков (например, последовательность [[1,2], [3,4 ]] возвращает [[1,3], [1,4], [2,3], [2,4]] ).

20
ответ дан 27 November 2019 в 22:41
поделиться

Вероятно, стоит пояснить, что эти два фрагмента не являются «аналогичными», и не следует ожидать связанных результатов. В частности, «монадическая» версия

map (\ x -> [x]) [0, 1, 2]

- это

mapM (\ x -> return [x]) [0, 1, 2]

Обратите внимание на дополнительный return .

В общем, return (map f x) совпадает с mapM (return. F) x .

Это связано с тем, что для монады списка x >> = f «сглаживает» результат применения f к x . Когда вы опускали return , результаты применения \ x -> [x] сводились к результату. Наличие дополнительного возврата отменяет дополнительное выравнивание.

15
ответ дан 27 November 2019 в 22:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: