map :: (a -> b) -> [a] -> [b]
fmap :: Functor f => (a -> b) -> f a -> f b
liftM :: Monad m => (a -> b) -> m a -> m b
Почему у нас есть три разные функции, которые делают практически одно и то же?
map :: (a -> b) -> [a] -> [b]
fmap :: Functor f => (a -> b) -> f a -> f b
liftM :: Monad m => (a -> b) -> m a -> m b
Почему у нас есть три разные функции, которые делают практически одно и то же?
map
существует для упрощения операций над списками и по историческим причинам (см. Какова точка карты в Haskell, когда есть fmap?).
3Вы можете спросить, почему нам нужна отдельная функция отображения. Почему бы просто не покончить с текущим отображение только списка, а вместо этого переименовать fmap? Ну, это хороший вопрос. обычный аргумент состоит в том, что кто-то, просто изучая Haskell, неправильно использует карту, скорее посмотрите ошибку о списках, чем о функторах.
- Typeclassopedia, стр. 20
fmap
и liftM
существуют потому, что монады не были автоматически функторами в Haskell:
Тот факт, что мы имеем как fmap, так и liftM, является неудачное следствие того, что класс типа Монада не требует экземпляр Functor, хотя математически говоря, каждая монада является функтор. Однако fmap и liftM существенно взаимозаменяемы, поскольку ошибка (в социальном, а не техническом смысле) для любого типа, являющегося экземпляром из Монады, не являясь также экземпляром Functor.
- Typeclassopedia, стр. 33
Изменить: история agustuss map
и fmap
:
Это не так, как это происходит. Случилось так, что тип карты был обобщен, чтобы охватить Functor в Haskell 1.3. I.e., в Haskell 1.3 fmap называлась картой. Затем это изменение было возвращено в Haskell 1.4 и введен fmap. Причина этого изменения была педагогической; при обучении Haskell новичкам очень общий тип карты затруднял понимание сообщений об ошибках. По-моему, это был неправильный способ решить проблему.