- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我浏览了一些关于 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
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 1
(16838,1103527590)
Prelude> :module Random
Prelude Random> randomRIO (1,6 :: Int)
(...) -- GHC prints some stuff here
6
Prelude Random> randomRIO (1,6 :: Int)
1
最佳答案
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
import Control.Monad.ST
import Data.STRef
bar :: Int
bar = runST (do x <- newSTRef 1
modifySTRef x (+ 2)
readSTRef x)
-- bar == 3
关于haskell - 如何在 Haskell 中以隐藏的方式初始化状态(就像 PRNG 一样)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1121340/
我是一名优秀的程序员,十分优秀!