为什么MonadTrans不是整个类型?

时间:2017-09-25 14:14:19

标签: haskell

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的实例实现中的所有类型变量?

2 个答案:

答案 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值(两个参数都提供)。