如何在两个 monad 之间共享状态?

发布于 2024-12-13 15:17:55 字数 370 浏览 5 评论 0原文

我遇到了以下 monad 问题:

假设我有一个标准 monad 状态,状态为 S = (LS, RS)。我还有另一个 monad:

newtype StateP a = StateP {runP :: S -> (a, RS)}

我想使用 StateP 执行一些计算,然后将状态与 State monad 中的状态合并:

merge m :: StateP() -> State()
merge m = do
 s@(l,r) <- get
 put (l, snd (runP m s))

它不起作用,但我不明白为什么?还有其他方法可以实现这样的功能吗?

I am stuck with following monad problem:

Let's say I have a standard monad State with state S = (LS, RS). I also have another monad:

newtype StateP a = StateP {runP :: S -> (a, RS)}

I want to perform some computation using StateP then merge state with state in State monad:

merge m :: StateP() -> State()
merge m = do
 s@(l,r) <- get
 put (l, snd (runP m s))

It is not working, but I don't get why? Is there another way to achieve such functionality?

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

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

发布评论

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

评论(3

無心 2024-12-20 15:17:55

如果您的代码几乎正确,请尝试

merge :: StateP() -> State()
merge m = do
    s@(l,r) <- get
    put (l, snd (runP m s))

但您确实需要向我们提供更多详细信息。

On the off-chance that your code is nearly right, try

merge :: StateP() -> State()
merge m = do
    s@(l,r) <- get
    put (l, snd (runP m s))

But you need to give us more details really.

剩余の解释 2024-12-20 15:17:55

您可以使用 monad 转换器,使用两个 monad 堆栈更明确地对这些需求进行建模:一个只能读取 LS,另一个可以读取和写入 LS

type ReadOnlyLS a  = ReaderT LS (State RS) a
type ReadWriteLS a = StateT LS (State RS) a

要在ReadWriteLS中运行ReadOnlyLS,我们只需从最外层的状态层中提取出LS,并将其交给内部计算的读取层即可并将计算结果提升回外部 monad:

merge :: ReadOnlyLS a -> ReadWriteLS a
merge m = get >>= lift . runReaderT m

You can use monad transformers to model these requirements more explicitly using two monad stacks: one that can only read LS and one that can both read and write LS.

type ReadOnlyLS a  = ReaderT LS (State RS) a
type ReadWriteLS a = StateT LS (State RS) a

To run a ReadOnlyLS within ReadWriteLS, we just need to extract LS from the outermost state layer, give it to the reader layer of the inner computation and lift the resulting computation back into the outer monad:

merge :: ReadOnlyLS a -> ReadWriteLS a
merge m = get >>= lift . runReaderT m
茶花眉 2024-12-20 15:17:55

RunP的功能是如何实现的?你是否为它重新定义了一个 monad 实例并拥有 getP/putP ?你的代码看起来不错,你能提供你使用的m吗?你有什么样的不当行为?

How do you achieve the functionality of RunP? Do you redefine a monad instance for it and have getP/putP? Your code seems fine, can you provide the m you use? What kind of misbehaviour do you get?

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