Functor,Applicative Functor和Monad之间的关系

时间:2011-12-28 16:17:21

标签: haskell

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

Every Monad is an Applicative Functor
Every Applicative Functor is a Functor

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

class Functor f => Applicative f where
  pure  :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

但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

根据Brent Yorgey的伟大typeclassopedia,monad的替代定义可能是:

class Applicative m => Monad' m where
  (>>=) :: m a -> (a -> m b) -> m b

这显然更简单会巩固Functor&lt; Applicative Functor&lt;单子。那么为什么这不是定义呢?我知道applicative functor是新的,但根据2010 Haskell Report第80页,这没有改变。这是为什么?

2 个答案:

答案 0 :(得分:27)

每个人都希望看到Applicative成为Monad的超类,但它会破坏如此多的代码(如果消除了return,每个当前的Monad实例都变得无效),每个人都想要推迟,直到我们可以扩展语言以这种方式避免破坏代码(see here为一个突出的提案)。

Haskell 2010在一般情况下是一个保守的渐进式改进,仅标准化了一些无争议的扩展并打破了one area中的兼容性,使标准与每个现有实现一致。事实上,Haskell 2010的图书馆甚至不包括Applicative - 人们对the standard library所期望的内容的标准化程度低于您的预期。

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

答案 1 :(得分:8)

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

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