结合 StateT 和 State monad

发布于 2024-10-01 06:22:11 字数 275 浏览 6 评论 0原文

假设我有一个函数

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 for
StateT (return . runState f)? Or in general, given a monad transformer with a corresponding monad, is there a library function for it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笑忘罢 2024-10-08 06:22:12

您要求的是从单子 StateT mStateT n 的映射(称为单子态射)。我将使用 mmorph 库,它提供了一组非常好的工具来处理单子态射。

执行State ->您正在寻找的 StateT m 变换,我们首先定义一个态射来泛化嵌入在 State 中的 Identity monad,

generalize :: Monad m => Identity a -> m a
generalize = return . runIdentity

接下来我们要提升这个态射作用于你的 StateT 的内部单子。也就是说,我们想要一个给出从一个 monad 到另一个 monad 的映射的函数(例如我们的泛化态射),它将给我们一个作用于 monad 转换器的基本 monad 的函数,例如 t身份a-> tm 。您会发现这类似于 mmorphMFunctor 类的 hoist 函数,

hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b

将各个部分组合在一起,

myAction :: State s Int
myAction = return 2

myAction' :: Monad m => StateT s m Int
myAction' = hoist generalize myAction

What you are asking for is a mapping (known as a monad morphism) from a monad StateT m to StateT n. I'll be using the the mmorph 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 the Identity monad embedded in State,

generalize :: Monad m => Identity a -> m a
generalize = return . runIdentity

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. our generalize 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 the hoist function of mmorph's MFunctor class,

hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b

Putting the pieces together,

myAction :: State s Int
myAction = return 2

myAction' :: Monad m => StateT s m Int
myAction' = hoist generalize myAction
め七分饶幸 2024-10-08 06:22:12

这样的函数并不是为所有 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 into ContT r IO because that would require turning a continuation in the IO monad (a -> IO r) into a pure continuation (a -> r).

溺深海 2024-10-08 06:22:11

更一般地说,您要做的是将转换应用于变压器堆栈的内层。对于两个任意 monad,类型签名可能如下所示:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 a) -> t m1 a -> t m2 a

基本上是一个更高级别的 fmap。事实上,将它与最终参数上的映射相结合可能更有意义:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 b) -> t m1 a -> t m2 b

显然,这在所有情况下都是不可能的,尽管当“源”单子是 Identity 它可能会更容易,但我可以想象为它起作用的地方定义另一个类型类。我认为典型的 monad 转换器库中没有类似的东西;然而,在 hackage 上浏览时会发现一些非常相似的内容 Monatron中:

class MonadT t => FMonadT t where
    tmap' :: FunctorD m -> FunctorD n -> (a -> b) 
             -> (forall x. m x -> n x) -> t m a -> t n b

tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b) 
        -> t m a -> t n a
tmap = tmap' functor functor id

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 确实有一个用于 StateTFMonadT 实例。

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:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 a) -> t m1 a -> t m2 a

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:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 b) -> t m1 a -> t m2 b

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 the Monatron package:

class MonadT t => FMonadT t where
    tmap' :: FunctorD m -> FunctorD n -> (a -> b) 
             -> (forall x. m x -> n x) -> t m a -> t n b

tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b) 
        -> t m a -> t n a
tmap = tmap' functor functor id

In the signature for tmap', the FunctorD types are basically ad-hoc implementations of fmap instead of using Functor 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 the category-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 a Functor instance (which any Monad must have) and a natural transformation, and any Monad has a natural transformation from the Identity monad provided by return, the function you want can be written generically for any instance of FMonadT as tmap (return . runIdentity)--assuming the "basic" monad is defined as a synonym for the transformer applied to Identity, 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 for StateT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文