【发布时间】:2016-07-26 16:31:00
【问题描述】:
考虑以下sn-p
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),这不仅不是MonadTrans,它的类型/种类不正确。
有什么方法可以完成我想做的事情,或者是时候尝试不同的方法了吗?
【问题讨论】:
-
您能举一些具体的例子来说明您希望
foo在实践中如何工作吗? -
假设你有一个
T类型,它可以被认为是一个V类型的容器和K类型的键。现在想象每个V也遵循这种模式。我想要foo :: StateT V (t (Either e)) a -> StateT T (ReaderT K (t (Either e))) a。这将对V进行有状态操作,并将它们提升为T上的有状态操作,这些操作具有K的环境。基本上是一个树形结构,我可以在不更改现有代码的情况下无限向上和向下扩展。 -
具体的例子在这里会更有帮助。并随时将其放在您的问题中,这样更容易阅读。
-
不幸的是,这是我所能得到的最具体的,这不是针对特定的应用程序或项目,这更像是实验性的思考。我会看看我是否能找到一些真正有用的情况。
-
一个monad转换器栈是一个栈。您无法指定堆栈底部的内容。
标签: haskell monads monad-transformers parametric-polymorphism