Haskell:如果遍历参数,则RWS上的单点固定点正在循环

问题描述 投票:2回答:2

我正在编写一个涉及RWS的程序,用于跟踪可变状态并生成一些日志。我的目的是定义一个计算,该计算对某些操作进行评估,收集后继状态,并根据该状态将某些内容附加到Writer日志的beginning中。最小示例:

type M = RWS () String [Int]

run a = evalRWS a () []

prepend s = tell (foldMap show s)

act = do
  tell "a"
  modify (1:)
  tell "b"

comp = mfix $ \s -> prepend s >> act >> get

这里,我使用MonadFix通过在act发生之前写日志来改变过去。它完美地返回"1ab"。但是,如果我使用M遍历状态,则会挂起:

prepend s = forM_ s (tell . show)

这种行为对我来说很奇怪,我不明白为什么这种计算会有所不同。由于第二种变体中的prepend不会在任何程度上改变状态,因此更难辩解。为什么该程序不收敛?我有什么可以解决的(inb4“ hehe fix”)吗?

[我知道我可以使用StateRWS部分来解决它,但是由于某些原因,我想避免使用它。

haskell monads lazy-evaluation fixed-point-iteration monadfix
2个回答
2
投票

仅在定义了forM_ s u的情况下才定义[s,但是这里smfix传递的占位符,仅当整个计算prepend s >> act >> get终止时才定义它。

您的第一个版本有效,因为它不需要检查状态就可以成对放置。

[mfix :: (a -> m a) -> m a不接受严格的功能f :: a -> m a(即f undefined = undefined)。]]

如果您有要tell的事物列表,那么一种比较懒惰的方法是在告诉它们之前将它们连接起来:

prepend s = tell (concatMap show s)

2
投票

这是因为forM_不是lazy

© www.soinside.com 2019 - 2024. All rights reserved.