gpt4 book ai didi

Haskell - StateT monad 内没有输出

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

为了熟悉 monad 转换器,我编写了以下代码:

data GlobalState = GlobalState {
rng :: StdGen
}

foo :: IO ()
foo =
evalStateT ( StateT $
\s ->
let (v, newrng) = roll $ rng s in
return (putStrLn $ show v,
s { rng = newrng })
) zeroState >>
putStrLn "See you soon."

zeroState :: GlobalState
zeroState = GlobalState {
rng = mkStdGen 0
}

roll :: StdGen -> (Int, StdGen)
roll gen = randomR (1, 6) gen

这个想法是初始化状态,将其用于 IO 操作,然后返回到普通 IO。然而,出了点问题,只打印了“See you Soon”,putStrLn $ show v 不产生任何输出。

所以问题是:我该如何修复它,最重要的是,为什么它不打印任何内容?

编辑:谢谢大家的回答,他们很有帮助。

最佳答案

以我的拙见,如果您使用 mtl 类型类,monad 转换器会更容易使用。这也导致了更通用的代码,因为它不会将您绑定(bind)到任何具体的数据类型。另外,我建议通常将“做什么”部分与“运行”部分分开。我重写了您的代码,希望能证明我的意思:

import System.Random
import Control.Monad.State

data GlobalState = GS { rng :: StdGen }

zeroState = GS { rng = mkStdGen 0 }

roll :: StdGen -> (Int,StdGen)
roll = randomR (1,6)

-- works with any concrete monad m that supplies IO and GlobalState state
foo :: (MonadIO m, MonadState GlobalState m) => m ()
foo = do
(v,gen) <- gets (roll . rng)
liftIO $ print v
put $ GS gen

-- commit to StateT here
evalFoo :: IO ()
evalFoo = evalStateT foo zeroState

好处是 foo 现在可以重用。例如,如果我们想滚动多次:

 evalFooN :: Int -> IO ()
evalFooN n = evalStateT (replicateM_ n foo) zeroState

关于Haskell - StateT monad 内没有输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41727562/

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