Functor,Applicative Functor和Monad之间的关系

Mag*_*ist 34 haskell

在阅读类型类时,我已经看到Functors,Applicative Functors和Monads之间的关系是严格增加的权力.函数是可以映射的类型.Applicative Functors可以使用某些效果执行相同的操作.Monads与可能不受限制的效果相同.此外:

Every Monad is an Applicative Functor
Every Applicative Functor is a Functor
Run Code Online (Sandbox Code Playgroud)

Applicative Functor的定义清楚地表明了这一点:

class Functor f => Applicative f where
  pure  :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

但Monad的定义是:

class Monad m where
  return :: a -> m a
  (>>=)  :: m a -> (a -> m b) -> m b
  (>>)   :: m a -> m b -> m b
  m >> n = m >>= \_ -> n
  fail   :: String -> m a
Run Code Online (Sandbox Code Playgroud)

根据Brent Yorgey的伟大类词库,monad的另一种定义可能是:

class Applicative m => Monad' m where
  (>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

这显然更简单,并将巩固Functor <Applicative Functor <Monad.那么为什么这不是定义呢?我知道applicative functor是新的,但根据2010年Haskell Report第80页,这没有改变.为什么是这样?

ehi*_*ird 27

每个人都希望看到Applicative成为Monad的超类,但它会破坏如此多的代码(如果return被淘汰,每个当前的Monad实例都变得无效),每个人都想要推迟,直到我们能够以这样的方式扩展语言,避免破坏代码(请参阅此处了解一个重要提案).

Haskell 2010总体上是一种保守的渐进式改进,仅标准化了一些无争议的扩展,并在一个领域打破了兼容性,使标准与每个现有实现一致.事实上,哈斯克尔2010的图书馆甚至不包括应用型-少了些什么人都来自期望标准库比你想象的是标准化的.

希望我们很快就会看到情况有所改善,但幸运的是,这通常只是一个轻微的不便(必须写liftM代替fmap通用代码等).


sep*_*p2k 8

此时更改Monad的定义会破坏许多现有代码(定义Monad实例的任何代码段)是值得的.

如果对变化有很大的实际好处,那么打破这种向后兼容性是值得的.在这种情况下,利益并不是那么大(而且主要是理论上的)并且不能证明这一数量的破损.

  • 每个人都希望看到Applicative成为Monad的超类,但它会打破如此多的代码,每个人都想要推迟,直到我们能够以避免破坏代码的方式扩展语言.[见这里](http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances)了解一个突出的提案. (3认同)