【问题标题】:Relationship between Functor, Applicative Functor, and MonadFunctor、Applicative Functor 和 Monad 之间的关系
【发布时间】:2012-01-29 07:29:26
【问题描述】:

在阅读类型类时,我发现 Functor、Applicative Functor 和 Monad 之间的关系是严格递增的权力。函子是可以映射的类型。 Applicative Functor 可以用某些效果做同样的事情。具有可能不受限制效果的单子相同。此外:

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 2010 Haskell Report 第80 页,这并没有改变。这是为什么呢?

【问题讨论】:

  • "Monads 与非限制性效果相同。"你是从哪里得到这个想法的?
  • 我当然犯了在 Monads 和 IO 之间放置等号的错误。说什么更正确?
  • @MagnusKronqvist:也许“依赖”是一个更好的词。 Applicative 和 Monad 之间的主要区别在于 (&lt;*&gt;) :: f (a -&gt; b) -&gt; f a -&gt; f b(=&lt;&lt;) :: (a -&gt; m b) -&gt; m a -&gt; m b 的类型,即结果的 m 部分可以依赖于输入中的 a,而对于 applicative,结果的 f 部分结果必须与a 输入的值无关。
  • class Applicative m =&gt; Monad'' m where join :: m (m a) -&gt; m a 是另一个可能的最小完整定义。 (也在 typeclassopedia 中注明)
  • @MagnusKronqvist:这里是 Monad 给你的我喜欢的 Applicative 的解释:Applicative 强制计算的结构是 static,而 Monad 允许它是 动态,取决于其他计算的结果。

标签: haskell


【解决方案1】:

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

Haskell 2010 总体上是一个保守的渐进式改进,仅标准化了一些无争议的扩展并破坏了one area 中的兼容性,以使该标准与每个现有实现保持一致。事实上,Haskell 2010 的库甚至不包括 Applicative——人们对 the standard library 的期望比你想象的要少。

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

【讨论】:

  • 不是每个人都希望Applicative成为Monad的超类
【解决方案2】:

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

只有在对更改有很大实际好处的情况下,才值得像这样打破向后兼容性。在这种情况下,好处并没有那么大(而且主要是理论上的),也不能证明这么多的破损是合理的。

【讨论】:

  • 你的意思是它会破坏兼容性? 'Applicative m => Monad m' 可能会破坏某些现有代码。但修复应该很容易,而且 Haskell 2010 已经不完全向后兼容。
  • Haskell 2010 完全向后兼容 Haskell 98 的实际实现,我相信;语法的重大变化是每个编译器都已经按照 Haskell 2010 要求的方式实现的。
  • 每个人都希望看到 Applicative 成为 Monad 的超类,但它会破坏太多代码,每个人都想推迟,直到我们能够以一种避免破坏代码的方式扩展语言。 See here 提出一项重要提案。
  • @ehird 谢谢,不过这应该是一个答案!
  • @MagnusKronqvist:我忍不住将其扩展为答案:)
猜你喜欢
  • 1970-01-01
  • 2011-11-05
  • 2012-11-12
  • 2019-06-30
  • 2015-07-02
  • 1970-01-01
  • 2013-11-07
相关资源
最近更新 更多