gpt4 book ai didi

haskell - 如何在 Haskell 中以隐藏的方式初始化状态(就像 PRNG 一样)?

转载 作者:行者123 更新时间:2023-12-03 11:57:13 24 4
gpt4 key购买 nike

我浏览了一些关于 State monad 的教程,我想我明白了。

例如,如 this nice tutorial :

import Data.Word

type LCGState = Word32

lcg :: LCGState -> (Integer, LCGState)
lcg s0 = (output, s1)
where s1 = 1103515245 * s0 + 12345
output = fromIntegral s1 * 2^16 `div` 2^32


getRandom :: State LCGState Integer
getRandom = get >>= \s0 -> let (x,s1) = lcg s0
in put s1 >> return x

好的,所以我可以使用 getRandom:
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 1
(16838,1103527590)

但是每次调用时我仍然需要将种子传递给 PRNG。我知道
Haskell 实现中可用的 PRNG 不需要:
Prelude> :module Random
Prelude Random> randomRIO (1,6 :: Int)
(...) -- GHC prints some stuff here
6
Prelude Random> randomRIO (1,6 :: Int)
1

所以我可能误解了 State monad,因为我在大多数教程中都能看到
似乎不是“持久”状态,而只是线程状态的一种便捷方式。

所以......我怎样才能拥有自动初始化的状态(可能来自一些
使用时间和其他不太可预测的数据的函数),例如 Random 模块
做?

非常感谢!

最佳答案

randomRIO使用 IO单子(monad)。这似乎在解释器中工作得很好,因为解释器也可以在 IO 中工作。单子(monad)。这就是您在示例中看到的内容;你实际上不能在代码的顶层做到这一点——你必须像所有的单子(monad)一样把它放在一个 do-expression 中。

在一般代码中,您应该避免使用 IO monad,因为一旦您的代码使用 IO monad,它就永远与外部状态相关联——您无法摆脱它(即,如果您有使用 IO monad 的代码,任何代码调用它也必须使用 IO monad;没有安全的方法可以“摆脱”它)。所以IO monad 应该只用于诸如访问外部环境之类的事情,这是绝对需要的事情。

对于像本地独立状态这样的事情,你不应该使用 IO monad。您可以使用 State如您所提到的 monad,或者您可以使用 ST单子(monad)。 ST monad 包含许多与 IO monad 相同的特性;即有 STRef可变单元格,类似于 IORef .和 IO 相比,ST 的好处是当你完成后,你可以调用 runST在 ST monad 上从 monad 中获取计算结果,这是 IO 无法做到的。

至于“隐藏”状态,这只是 Haskell for monads 中 do 表达式语法的一部分。如果您认为需要显式传递状态,那么您没有正确使用 monad 语法。

这是在 IO Monad 中使用 IORef 的代码:

import Data.IORef
foo :: IO Int -- this is stuck in the IO monad forever
foo = do x <- newIORef 1
modifyIORef x (+ 2)
readIORef x
-- foo is an IO computation that returns 3

这是使用 ST monad 的代码:
import Control.Monad.ST
import Data.STRef
bar :: Int
bar = runST (do x <- newSTRef 1
modifySTRef x (+ 2)
readSTRef x)
-- bar == 3

代码的简单性本质上是一样的;除了在后一种情况下,我们可以从 monad 中获取值,而在前一种情况下,我们不能不将其放入另一个 IO 计算中。

关于haskell - 如何在 Haskell 中以隐藏的方式初始化状态(就像 PRNG 一样)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1121340/

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