gpt4 book ai didi

haskell - 无法理解 State Monad 如何在此代码中获取它的状态

转载 作者:行者123 更新时间:2023-12-02 17:01:11 25 4
gpt4 key购买 nike

我有点理解 State Monad 在顺序执行中传播新值的用处。但是在下面的代码中,我无法理解 addResult 每次评估时如何以及在何处获取更新状态。

fizzBuzz :: Integer -> String
fizzBuzz n
| n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Buzz"
| n `mod` 3 == 0 = "Fizz"
| otherwise = show n

fizzbuzzList :: [Integer] -> [String]
fizzbuzzList list = execState (mapM_ addResult list) []

addResult :: Integer -> State [String] ()
addResult n = do
xs <- get
let result = fizzBuzz n
put (result : xs)

main :: IO ()
main = mapM_ putStrLn $ fizzbuzzList [1..100]

此代码计算产生

1, 2, Fizz...

我只是想不通 addResult 产生的新值是如何附加到先前产生的列表中的。你能帮我理解 mapM_ addResult list 是如何做到这一点的吗?

最佳答案

正如您正确观察到的那样,State monad 用于通过一系列计算将一些外部“状态”值串联起来。但是,您询问如何在列表 list 的每个值上多次调用您的函数 addResult::Integer -> State [String] () 时“保持”这种状态.诀窍在于 mapM_ 的定义。我们将从考虑更简单的函数 mapM 开始:

mapM f [] = return []
mapM f (x:xs) = do
fx <- f x
fxs <- mapM f xs
return (fx : fxs)

如果我们用例如示例列表 [x1,x2,x3,x4,...,xn] 在心理上“扩展”这个递归定义,我们将观察到值mapM f [x1,...,xn] 将是另一个单子(monad)计算:

do
fx1 <- f x1
fx2 <- f x2
-- etc.
fxn <- f xn
return [fx1,fx2,...,fxn]

所以 mapM 基本上将一堆单子(monad)计算“粘在一起”成一个大计算,按顺序将它们一起运行。这解释了如何构建列表而不是生成许多较小的列表:addResult 开头的 get 获取上次运行的状态 ,而不是从一开始,因为您正在一起运行所有计算,如下所示:

do
fl0 <- addResult (list !! 0)
fl1 <- addResult (list !! 1)
-- etc. like before

(如果你仔细阅读,你会发现我一直在谈论mapM,但你实际上使用了mapM_。它们完全一样,除了后者返回 ()。)

关于haskell - 无法理解 State Monad 如何在此代码中获取它的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54117352/

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