Я прошел несколько руководств по монаде State и, кажется, уловил идею.
Например, как в этом замечательном руководстве:
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 каждый раз, когда я его вызываю. Я знаю, что PRNG, доступный в реализациях Haskell, не нуждается в этом:
Prelude> :module Random
Prelude Random> randomRIO (1,6 :: Int)
(...) -- GHC prints some stuff here
6
Prelude Random> randomRIO (1,6 :: Int)
1
Так что я, вероятно, неправильно понял монаду State, потому что то, что я мог видеть в большинстве руководств, похоже, не является «постоянным» состоянием, а просто удобным способом для состояния потока.
Итак... Как я могу иметь состояние, которое автоматически инициализируется (возможно, из какой-то функции, которая использует время и другие не очень предсказуемые данные), как это делает модуль Random?
Большое спасибо!