任意monad变换器堆栈在类型变量

时间:2016-07-26 16:31:00

标签: haskell monads monad-transformers parametric-polymorphism

考虑以下代码段

import Control.Monad.Trans
import Control.Monad.Trans.Except
import Control.Monad.Trans.State

newtype MyTransT m a = MyTransT (m a)

foo :: (MonadTrans t, Monad (t (Either e))) => MyTransT (t (Either e)) a -> a
foo = undefined

bar :: MyTransT (StateT Int (Either e)) a
bar = undefined

baz :: MyTransT (StateT Int (StateT Int (Either e))) a
baz = undefined

x = foo bar -- works

y = foo baz -- doesn't work

本质上,我试图创建一个接受monad变换器堆栈的函数,指定堆栈的顶部和底部,而中间可以是任何东西。

在我为foo baz Couldn't match type ‘StateT Int (Either e1)’ with ‘Either e0’拒绝t被拒绝的原因后,我终于想到,在这种情况下,我假设StateT Int (StateT Int)是{{} 1}}这不仅不是MonadTrans,而且没有正确输入/打字。

有没有办法完成我想要做的事情,或者是时候尝试不同的方法了?

1 个答案:

答案 0 :(得分:0)

foo baz未进行类型检查的原因是因为t不是Either e monad上的变换器 - 它是StateT Int (Either e)上的变换器单子。

以下是解析方式:

 baz :: MyTransT (StateT Int (StateT Int (Either e))) a
                  \________/ \_____________________/
                       t            m                 a

请注意m <{1}}。

你可以创建一个新的变换器,例如Either e,然后写 巴兹这样:

StateTIntStateTInt

然后它会输入检查。例如:

 baz :: MyTransT (StateTIntStateInt (Either e)) a

然而,即使你解决类型问题,我怀疑你会去 能够编写函数type StateTIntStateTInt = StateT (Int,Int) baz' :: MyTransT (StateTIntStateTInt (Either e)) a baz' = undefined test = foo baz' 。考虑应该返回什么 对于此foo的具体值:

bar

应该{​​{1}}返回什么Int值?