为什么我们有map,fmap和liftM?

问题描述 投票:91回答:1
map :: (a -> b) -> [a] -> [b]

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

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

为什么我们有三个不同的功能,它们基本上是一回事?

list haskell monads redundancy functor
1个回答
86
投票

map的存在是为了简化列表操作和历史原因(参见What's the point of map in Haskell, when there is fmap?)。

你可能会问为什么我们需要一个单独的map函数。为什么不放弃当前仅列表映射函数,并将fmap重命名为map?嗯,这是一个很好的问题。通常的论点是,有人在学习Haskell时,如果错误地使用地图,则更倾向于看到关于列表的错误,而不是关于Functors的错误。

- Typeclassopedia,第20页

fmapliftM之所以存在,是因为monads不是Haskell中的自动仿函数:

我们同时拥有fmap和liftM的事实是Monad类型类不需要Functor实例这一事实的不幸后果,即使从数学上讲,每个monad都是一个算子。但是,fmap和liftM本质上是可以互换的,因为它是一个bug(在社交而不是技术意义上),任何类型的Monad实例都不是Functor的实例。

- Typeclassopedia,第33页

编辑:agustuss的mapfmap的历史:

实际上并不是这样的。发生的事情是,地图的类型被概括为涵盖Haskell 1.3中的Functor。即,在Haskell 1.3中,fmap被称为map。然后在Haskell 1.4中恢复此更改并引入了fmap。这种变化的原因是教学法;在向初学者教授Haskell时,非常一般的地图类型使得错误消息更难以理解。在我看来,这不是解决问题的正确方法。

- What's the point of map in Haskell, when there is fmap?

© www.soinside.com 2019 - 2024. All rights reserved.