0

我被以下单子问题困扰:

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

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))

它不起作用,但我不明白为什么?有没有另一种方法来实现这样的功能?

4

3 回答 3

2

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

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

但是你真的需要给我们更多的细节。

于 2011-11-04T18:53:20.187 回答
1

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

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

要运行ReadOnlyLSwithin ReadWriteLS,我们只需LS要从最外层的状态层中提取,将其提供给内部计算的读取器层,并将结果计算提升回外部 monad:

merge :: ReadOnlyLS a -> ReadWriteLS a
merge m = get >>= lift . runReaderT m
于 2011-11-04T19:55:48.270 回答
0

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

于 2011-11-04T18:41:59.130 回答