为什么monad变换器不能限制产生monad?

时间:2012-12-03 15:45:13

标签: haskell monads typeclass monad-transformers

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感到困惑。

1 个答案:

答案 0 :(得分:14)

您建议如下:

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

...但这真的意味着你想要的吗?对于所有t MonadTrans m :: * -> *m的实例,您似乎想要表达“类型Monad可能是t m的实例” ,Monad也是t“的实例。

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

在一般情况下,类型类的每个参数都是一个独立的“参数”,这个事实一直是人们试图使用MPTC时头痛和GHC扩展的丰富来源。

这并不是说无论如何都不能使用这样的定义 - 正如你所指出的那样,目前的定义也不理想。古老的问题“为什么Functor不是ConstraintKinds”是相关的,而这些问题有助于推动最近的MonadTrans愚蠢行为。

这里的“为什么不”的最终答案几乎可以肯定是Daniel Fischer在评论中给出的答案 - 因为{{1}}是非常核心的功能,所以要让它依赖于一些可怕的级联越来越神秘的GHC扩展。