考虑以下代码段
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
,而且没有正确输入/打字。
有没有办法完成我想要做的事情,或者是时候尝试不同的方法了?
答案 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值?