【问题标题】:Why aren't monad transformers constrained to yield monads?为什么 monad 转换器不被限制为产生 monad?
【发布时间】:2012-11-21 02:57:29
【问题描述】:

MonadTrans 类中:

class MonadTrans t where
    -- | Lift a computation from the argument monad to the constructed monad.
    lift :: Monad m => m a -> t m a

为什么t m 不被限制为 Monad?即,为什么不:

{-# LANGUAGE MultiParamTypeClasses #-}
class Monad (t m) => MonadTrans t m where
  lift :: Monad m => m a -> t m a

如果答案是“因为它就是这样”,那很好 - 只是让 n008 感到困惑。

【问题讨论】:

  • 如果t是一个monad,那么它的类型必须是* -> *,而t m a的类型是* -> * -> *,我想(也许我错了)。
  • 将 monad 操作应用于 t m 的“值”是否有意义?是否有 t m 的值?
  • 糟糕,并不是要忽略这个限制。添加它。谢谢。
  • @EarlGray,不,没有。 t m 有种类* -> *,类型(即值的类型)有种类*。但同样将 monad 操作应用于 Maybe 的“值”是没有意义的,因为没有。
  • 类按原样定义而不是按照您的方式定义的一个原因是,至少对于transformers 包而言,可移植性。 MPTC 是一种语言扩展,因此使用起来不方便。

标签: haskell monads typeclass monad-transformers


【解决方案1】:

您提出以下建议:

class Monad (t m) => MonadTrans t m where
    lift :: Monad m => m a -> t m a

...但这真的是你想要的吗?您似乎想表达类似“类型t 可能是MonadTrans 的实例,如果对于所有m :: * -> * 其中mMonad 的实例,t m 也是@ 的实例987654328@"。

上面的类定义实际上所说的更像是“类型tm 可能构成MonadTrans 的实例,如果对于这些特定类型,t m 是一个实例Monad"。仔细考虑差异,以及可能不是您想要的实例的隐含可能性。

在一般情况下,类型类的每个参数都是一个独立的“参数”,当人们尝试使用 MPTC 时,这一事实一直是令人头疼的问题和 GHC 扩展的来源。

这并不是说无论如何都不能使用这样的定义——正如您所指出的,当前的定义也不理想。古老的问题“为什么Data.Set 不是Functor”是相关的,这些问题有助于激发最近的ConstraintKinds tomfoolery。

这里“为什么不”的最终答案几乎可以肯定是 Daniel Fischer 在 cmets 中给出的答案——因为 MonadTrans 是非常核心的功能,因此不希望让它依赖于一些越来越神秘的可怕级联GHC 扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2018-02-06
    • 2012-08-26
    • 1970-01-01
    相关资源
    最近更新 更多