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

fre*_*low 96 monads redundancy haskell list functor

map :: (a -> b) -> [a] -> [b]

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

liftM :: Monad m => (a -> b) -> m a -> m b
Run Code Online (Sandbox Code Playgroud)

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

li.*_*idm 88

map存在是为了简化列表上的操作和历史原因(当有fmap时,请参阅Haskell中的地图点是什么?).

3你可能会问为什么我们需要一个单独的地图功能.为什么不放弃当前仅列表映射函数,并将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时,非常一般的地图类型使得错误消息更难以理解.在我看来,这不是解决问题的正确方法.

- 当有fmap时,Haskell中的地图有什么意义?

  • 而且,从我的角度来看,在改变@augustss描述之后十多年来第一次遇到Haskell的人,以及花了很多时间来帮助那些正在学习这门语言的人,这一点并不清楚它甚至帮助了无论如何.当然不足以抵消无用的冗余(这本身就会导致人们提出像这样的问题); `Functor`类太常见了,无法忽略,初学者常常被错误信息搞糊涂了! (12认同)
  • 我们不能删除`liftM`吗?让代码中断,谁在乎,通常需要不到2天的代码才能在github上修复,然后上传到hackage上.还是我疯狂而疯狂? (10认同)
  • @Tarrasch:不是每个人都使用 github,并不是所有的包都有及时更新的良好记录,我倾向于在 do-block 中使用 `liftM` 而不是 `fmap`,因为它更适合当我使用 `liftM2` 等时。 (2认同)