Государственная монада, последовательности случайных чисел и монадический код
Я пытаюсь понять Государственную Монаду, и с этой целью я хотел написать монадический код, который генерировал бы последовательность случайных чисел, используя линейный конгруэнтный генератор (вероятно, не очень хорошо, но я собираюсь просто изучить Государственную монаду, а не строить хорошая библиотека RNG).
Генератор только это (я хочу создать последовательностьBool
s для простоты):
type Seed = Int
random :: Seed -> (Bool, Seed)
random seed = let (a, c, m) = (1664525, 1013904223, 2^32) -- some params for the LCG
seed' = (a*seed + c) `mod` m
in (even seed', seed') -- return True/False if seed' is even/odd
Дон»не беспокойтесь о числах, это всего лишь правило обновления для начального числа, которое (согласно Числовым Рецептам) должно генерировать псевдослучайную последовательностьInt
s. Теперь, если я хочу генерировать случайные числа последовательно, ябуду делать:
rand3Bools :: Seed -> ([Bool], Seed)
rand3Bools seed0 = let (b1, seed1) = random seed0
(b2, seed2) = random seed1
(b3, seed3) = random seed2
in ([b1,b2,b3], seed3)
Итак, я мог бы избежать этого шаблона с помощью государственной монады:
import Control.Monad.State
data Random {seed :: Seed, value :: Bool}
nextVal = do
Random seed val Seed -> [Bool]
getNRand n seed = evalState (getNRandStates n) (Random seed True)
Хорошо, это работает нормально и дать мне список n псевдослучайныхBool
s для каждого данного семени. Но...
Я могу читать то, что ямы сделали (в основном на основе этого примера:http://www.haskell.org/pipermail/beginners/2008-September/000275.html ) и повторить это, чтобы делать другие вещи. Но я неЯ не могу понять, чтона самом деле происходит за do-нотацией и монадическими функциями (например, replicateM).
Может ли кто-нибудь помочь мне с некоторыми из этих сомнений?
1 - ямы пытались отключить функцию nextVal, чтобы понять, что она делает, но я не смогт. Я могу догадаться, что он извлекает текущее состояние, обновляет его, а затем передает его перед следующим вычислением, но это просто основано на чтении этого do-sugar, как если бы оно было английским.
Как мне действительно отключить эту функцию от оригинала >>= и возвращать функции пошагово?
2 - я не могт понять, что именноput
а такжеget
функции делают. Я могу догадаться, что онипакет» а также "распаковать» штат. Но механика, стоящая за сахаром до сих пор для меня неясна.
Что ж, любые другие общие замечания по поводу этого кода приветствуются. Иногда я с Haskell упал, что я могу создать код, который работает и делать то, что я ожидаю, но я не могу "следить за оценкой Насколько я'Я привык делать с императивными программами.