2017-09-25 65 views
0

的MonadTrans类型定义如下:为什么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中的所有类型变量?

+2

Haskell类中的_kinds_类型变量是从类声明中如何使用这些变量推断出来的。在这里,'t ::(* - > *) - > * - > *'因为它需要一些'm'和'a',因为它是一个类型(和'm :: * - > *'因为它需要'a'来应用它,因为它是一种类型)。 – Alec

回答

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需要。

2

因为当你完全运用你留下的一个表达式代表一个类型,但你想陈述关于类型函数的事情,在这种情况下,种类(* -> *) -> (* -> *),这是需要一个monad(* -> * +法律)并产生一个monad。类的任何实例就是这样一个变压器t给定一个单子m让你电梯m a到值(t m) a。你修正了多少个参数决定你是否谈论变压器(没有参数提供),变换单子(提供了一个参数 - 你希望变压器作用的单子)或单子值(提供了两个参数)。

相关问题