结合 StateT 和 State monad
假设我有一个函数
f :: State [Int] Int
和一个函数:
g :: StateT [Int] IO Int
我想在 g
中使用 f
并在它们之间传递状态。有没有库函数StateT(返回.runState f)
?或者一般来说,给定一个带有相应 monad 的 monad 转换器,是否有一个库函数?
Lets say I have a function
f :: State [Int] Int
and a function:
g :: StateT [Int] IO Int
I want to use f
in g
and pass the state between them. Is there a library function forStateT (return . runState f)
? Or in general, given a monad transformer with a corresponding monad, is there a library function for it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您要求的是从单子
StateT m
到StateT n
的映射(称为单子态射)。我将使用mmorph
库,它提供了一组非常好的工具来处理单子态射。执行
State ->您正在寻找的 StateT m 变换,我们首先定义一个态射来泛化嵌入在
State
中的Identity
monad,接下来我们要提升这个态射作用于你的 StateT 的内部单子。也就是说,我们想要一个给出从一个 monad 到另一个 monad 的映射的函数(例如我们的泛化态射),它将给我们一个作用于 monad 转换器的基本 monad 的函数,例如 t身份a-> tm 。您会发现这类似于
mmorph
的MFunctor
类的hoist
函数,将各个部分组合在一起,
What you are asking for is a mapping (known as a monad morphism) from a monad
StateT m
toStateT n
. I'll be using the themmorph
library, which provides a very nice set of tools for working with monad morphisms.To perform the
State -> StateT m
transform you are looking for, we'll start by defining a morphism to generalize theIdentity
monad embedded inState
,Next we'll want to lift this morphism to act on the inner monad of your
StateT
. That is, we want a function which given a mapping from one monad to another (e.g. ourgeneralize
morphism), will give us a function acting on the base monad of a monad transformer, e.g.t Identity a -> t m a
. You'll find this resembles thehoist
function ofmmorph
'sMFunctor
class,Putting the pieces together,
这样的函数并不是为所有 monad 转换器定义的。例如,
Cont r
单子无法提升为ContT r IO
,因为这需要在 IO 单子中进行延续(a -> IO r
)转换为纯延续(a -> r
)。Such a function is not definable for all monad transformers. The
Cont r
monad, for example, can't be lifted intoContT r IO
because that would require turning a continuation in the IO monad (a -> IO r
) into a pure continuation (a -> r
).更一般地说,您要做的是将转换应用于变压器堆栈的内层。对于两个任意 monad,类型签名可能如下所示:
基本上是一个更高级别的
fmap
。事实上,将它与最终参数上的映射相结合可能更有意义:显然,这在所有情况下都是不可能的,尽管当“源”单子是
Identity 它可能会更容易,但我可以想象为它起作用的地方定义另一个类型类。我认为典型的 monad 转换器库中没有类似的东西;然而,在 hackage 上浏览时会发现一些非常相似的内容 在
Monatron
包中:在
tmap'
的签名中,FunctorD
类型基本上是fmap
的临时实现,而不是直接使用Functor
实例。此外,对于两个类似 Functor 的类型构造函数 F 和 G,具有类似
(forall a.F a -> G a)
类型的函数描述 从 F 到 G 的自然转换。您很可能想要在category-extras
包中的某个地方找到变换器映射的另一种实现,但我不确定 monad 变换器的类别理论版本是什么,所以我不知道它可能被称为什么。由于
tmap
仅需要一个Functor
实例(任何Monad
都必须具有)和一个自然转换,以及任何Monad
具有由return
提供的Identity
monad 的自然转换,您想要的函数可以为任何FMonadT
实例一般地编写为tmap (return . runIdentity)
——假设“基本”monad 被定义为应用于Identity
的转换器的同义词,无论如何,这通常是转换器库的情况。回到您的具体示例,请注意 Monatron 确实有一个用于
StateT
的FMonadT
实例。In even more general, what you're trying to do is apply a transformation to an inner layer of a transformer stack. For two arbitrary monads, the type signature might look something like this:
Basically a higher-level
fmap
. In fact, it would probably make even more sense to combine it with a map over the final parameter as well:Clearly this isn't going to be possible in all cases, though when the "source" monad is
Identity
it's likely to be easier, but I can imagine defining another type class for the places it does work. I don't think there's anything like this in the typical monad transformer libraries; however, some browsing on hackage turns up something very similar in theMonatron
package:In the signature for
tmap'
, theFunctorD
types are basically ad-hoc implementations offmap
instead of usingFunctor
instances directly.Also, for two Functor-like type constructors F and G, a function with a type like
(forall a. F a -> G a)
describes a natural transformation from F to G. There's quite possibly another implementation of the transformer map that you want somewhere in thecategory-extras
package but I'm not sure what the category-theoretic version of a monad transformer would be so I don't know what it might be called.Since
tmap
requires only aFunctor
instance (which anyMonad
must have) and a natural transformation, and anyMonad
has a natural transformation from theIdentity
monad provided byreturn
, the function you want can be written generically for any instance ofFMonadT
astmap (return . runIdentity)
--assuming the "basic" monad is defined as a synonym for the transformer applied toIdentity
, at any rate, which is generally the case with transformer libraries.Getting back to your specific example, note that Monatron does indeed have an instance of
FMonadT
forStateT
.