Государственная монада, последовательности случайных чисел и монадический код

Я пытаюсь понять Государственную Монаду, и с этой целью я хотел написать монадический код, который генерировал бы последовательность случайных чисел, используя линейный конгруэнтный генератор (вероятно, не очень хорошо, но я собираюсь просто изучить Государственную монаду, а не строить хорошая библиотека RNG).

Генератор только это (я хочу создать последовательностьBools для простоты):

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 

Дон»не беспокойтесь о числах, это всего лишь правило обновления для начального числа, которое (согласно Числовым Рецептам) должно генерировать псевдослучайную последовательностьInts. Теперь, если я хочу генерировать случайные числа последовательно, ябуду делать:

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 псевдослучайныхBools для каждого данного семени. Но...

Я могу читать то, что ямы сделали (в основном на основе этого примера:http://www.haskell.org/pipermail/beginners/2008-September/000275.html ) и повторить это, чтобы делать другие вещи. Но я неЯ не могу понять, чтона самом деле происходит за do-нотацией и монадическими функциями (например, replicateM).

Может ли кто-нибудь помочь мне с некоторыми из этих сомнений?

1 - ямы пытались отключить функцию nextVal, чтобы понять, что она делает, но я не смогт. Я могу догадаться, что он извлекает текущее состояние, обновляет его, а затем передает его перед следующим вычислением, но это просто основано на чтении этого do-sugar, как если бы оно было английским.

Как мне действительно отключить эту функцию от оригинала >>= и возвращать функции пошагово?

2 - я не могт понять, что именноput а такжеget функции делают. Я могу догадаться, что онипакет» а также "распаковать» штат. Но механика, стоящая за сахаром до сих пор для меня неясна.

Что ж, любые другие общие замечания по поводу этого кода приветствуются. Иногда я с Haskell упал, что я могу создать код, который работает и делать то, что я ожидаю, но я не могу "следить за оценкой Насколько я'Я привык делать с императивными программами.

Ответы на вопрос(3)

Ваш ответ на вопрос