MonadTrans类型定义如下:
class MonadTrans t where
-- | Lift a computation from the argument monad
-- to the constructed monad.
lift :: (Monad m) => m a -> t m a
并查看执行:
instance MonadTrans (ExceptT e) where
lift = ExceptT . liftM Right
ExceptT
的类型构造函数有三个类型变量:
newtype ExceptT e m a =
ExceptT { runExceptT :: m (Either e a)) }
因此类型构造函数ExceptT
没有完全应用类型
为什么有可能,更不用说MonadTrans
ExceptT e
的实例实现中的所有类型变量?
答案 0 :(得分:4)
首先要提到的是lift
定义使用“无点”风格。它相当于
instance MonadTrans (ExceptT e) where
lift x = ExceptT (liftM Right x)
现在回答这个问题。 instance MonadTrans
下的表达式为(ExceptT e)
。这是类声明中的替换t
。让我们在lift
签名中替换它:
instance MonadTrans (ExceptT e) where
-- (this was t)
-- ||
-- \/
lift :: (Monad m) => m a -> ExceptT e m a
lift = ExceptT (liftM Right x)
在此表达式liftM Right x :: m (Either a b)
中,这正是ExceptT
所采用的。
答案 1 :(得分:2)
因为当你完全应用时,你会留下一个代表一个类型的表达式,但是你想要陈述关于类型函数的东西,在这种类型为(* -> *) -> (* -> *)
的情况下,这是一个需要monad的东西( * -> *
+法律)并生成一个monad。该类的任何实例都是这样的转换器 t
,给定monad m
允许您将值m a
提升为值{{ {1}}。你修复了多少个参数决定你是否谈论变换器(没有提供参数),变换monad (提供一个参数 - 你希望变换器作用的monad),或一个monadic值(两个参数都提供)。