gpt4 book ai didi

haskell - 在 Haskell 中与 State monad 一起工作

转载 作者:行者123 更新时间:2023-12-03 14:54:36 25 4
gpt4 key购买 nike

我一直在一点一点地学习一些 Haskell,并且正在(慢慢地)致力于理解 State monad,尝试编写一个重复状态计算的函数,直到状态满足一些 bool 测试,并将返回的值收集到一个列表中以获得整体结果.我终于成功了:

collectUntil :: (s -> Bool) -> State s a -> State s [a]
collectUntil f s = do s0 <- get
let (a,s') = runState s s0
put s'
if (f s') then return [a] else liftM (a:) $ collectUntil f s

以便
simpleState = state (\x -> (x,x+1))

*Main> evalState (collectUntil (>10) simpleState) 0
[0,1,2,3,4,5,6,7,8,9,10]

这是该任务的合理功能,还是有更惯用的方法?

最佳答案

你犯的错误与我刚开始编写单子(monad)代码时所犯的错误完全相同——太复杂了,过度使用 liftM使用不足>>= (等效地,未充分使用 <- 符号)。

理想情况下,您不必提及 runStateevalState在状态单子(monad)里面。您想要的功能如下:

  • 阅读当前状态
  • 如果满足谓词f , 然后返回
  • 如果不是,则运行计算 s并将其结果添加到输出

  • 您可以直接这样做:
    collectUntil f comp = do
    s <- get -- Get the current state
    if f s then return [] -- If it satisfies predicate, return
    else do -- Otherwise...
    x <- comp -- Perform the computation s
    xs <- collectUntil f comp -- Perform the rest of the computation
    return (x:xs) -- Collect the results and return them

    请注意,如果它们是同一个 monad 的一部分,您可以嵌套 do 语句!这非常有用——它允许您在一个 do block 内进行分支,只要 if 语句的两个分支都指向相同的单子(monad)类型。

    此函数的推断类型为:
    collectUntil :: MonadState t m => (t -> Bool) -> m a -> m [a]

    如果您愿意,您可以将其专门用于 State s键入,尽管您不必:
    collectUntil :: (s -> Bool) -> State s a -> State s [a]

    甚至可能最好保留更一般的状态,以防您以后想使用不同的 monad。

    直觉是什么?

    每当 s是一个有状态的计算,你在状态单子(monad)里,你可以做
    x <- s

    x现在将得到计算结果(就像您调用了 evalState 并以初始状态馈送)。如果你需要检查状态,你可以做
    s' <- get

    s'将具有当前状态的值。

    关于haskell - 在 Haskell 中与 State monad 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11250328/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com