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

Mat*_*ick 14 monads haskell 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
Run Code Online (Sandbox Code Playgroud)

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

{-# LANGUAGE MultiParamTypeClasses #-}
class Monad (t m) => MonadTrans t m where
  lift :: Monad m => m a -> t m a
Run Code Online (Sandbox Code Playgroud)

如果答案是"因为那就是它的方式",那很好 - 这只会让n008感到困惑.

C. *_*ann 14

你建议如下:

class Monad (t m) => MonadTrans t m where
    lift :: Monad m => m a -> t m a
Run Code Online (Sandbox Code Playgroud)

......但这真的意味着你想要的吗?似乎你想要表达类似"一个类型t可能是MonadTransif 的实例,对于所有m :: * -> *在哪里m的实例Monad,t m也是一个实例Monad".

上面的类定义实际上说的更像是"类型,t并且m可能构成MonadTransif 的实例,对于那些特定类型,t m是一个实例Monad".仔细考虑差异,以及可能不是您想要的实例的隐含可能性.

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

这并不是说无论如何都不能使用这样的定义 - 正如你所指出的那样,目前的定义也不理想.这个古老的问题"为什么Data.Set不是一个Functor"是相关的,这些问题有助于激发最近的ConstraintKinds蠢事.

这里"为什么不"的最终答案几乎肯定是Daniel Fischer在评论中给出的答案 - 因为它MonadTrans是非常核心的功能,所以它依赖于一些日益神秘的GHC扩展的可怕级联是不可取的.