Почему у нас есть карта, fmap и liftM? - PullRequest
92 голосов
/ 18 сентября 2011
map :: (a -> b) -> [a] -> [b]

fmap :: Functor f => (a -> b) -> f a -> f b

liftM :: Monad m => (a -> b) -> m a -> m b

Почему у нас есть три разные функции, которые делают одно и то же?

1 Ответ

86 голосов
/ 18 сентября 2011

map существует для упрощения операций со списками и по историческим причинам (см. Какой смысл карты в Haskell, когда есть fmap? ).

Вы можете спросить, зачем нам нужна отдельная функция карты. Почему бы просто не покончить с текущим Функция отображения только для списка, и вместо этого переименовать fmap в map? Ну, это хороший вопрос. Обычный аргумент состоит в том, что кто-то, только изучающий Haskell, при неправильном использовании карты будет лучше увидеть ошибку в списках, чем в функторах.

- Typeclassopedia , стр. 20

fmap и liftM существуют, потому что монады не были автоматически функторами в Haskell:

Тот факт, что у нас есть и fmap, и liftM, является Печальное последствие того факта, что класс типа Monad не требует экземпляр Functor, хотя математически говоря, каждая монада функтор. Тем не менее, fmap и liftM по существу взаимозаменяемы, так как это ошибка (в социальном, а не техническом смысле) для любого типа, чтобы быть экземпляром Монады, не являясь также экземпляром Функтора.

- Typeclassopedia , стр. 33

Редактировать: история agustuss map и fmap:

На самом деле это не так. Случилось так, что тип карты был обобщен, чтобы охватить Functor в Haskell 1.3. Т.е. в Haskell 1.3 fmap назывался map. Это изменение было затем отменено в Haskell 1.4, и было введено fmap. Причина этого изменения была педагогической; При обучении Haskell новичкам очень общий тип карт усложнил понимание сообщений об ошибках. На мой взгляд, это был неправильный способ решения проблемы.

- Какой смысл карты в Haskell, когда есть fmap?

...