Начав с Haskell и остановившись на State Monad ...
Итак, я пытаюсь разобраться с Монадой состояний в Haskell, и чтобы понять ее, я пишу код для генерации последовательностей PRBS. Для заинтересованных людей это описано в статье «Псевдослучайные последовательности и массивы», бесплатную копию которой можно получить по адресу doi: 10.1109 / PROC.1976.10411.
Суть сотрудничества очень проста. У вас есть сдвиговый регистр и генераторный полином. Генераторный полином сообщает вам, какие биты сдвигового регистра нужно взять и суммировать (по модулю 2), чтобы получить старший бит сдвигового регистра. На следующей итерации вы берете этот вычисленный MSB и прикрепляете его к MSB регистра сдвига после выполнения операции сдвига вправо.
Код для этого без монад действительно прост:
import Data.List
m = (4::Int) -- This is the degree of the polynomial
p = tail $ [4, 1, 0] -- This is a actual polynomial
s = 1 : replicate (m-1) 0 -- This is the initial state. Note that the head is the MSB
chSt poly s = msb poly s : init s -- changes the shift register 's'
where
msb poly s = let tot = sum $ map ( (reverse s) !! ) poly
in tot `mod` 2
word p s = take n $ bits p s
where
bits p s = last s : bits p (chSt p s)
n = 2 ^ (length s) - 1
Результат выглядит следующим образом:
[ghci] word p s --> [0,0,0,1,0,0,1,1,0,1,0,1,1,1,1]
чего я и хочу.
Теперь, конечно, поскольку регистр сдвига можно рассматривать как состояние, которое мы модифицируем, мы можем использовать для этой цели монаду состояния. Возможно, это слишком простая проблема, чтобы узнать о монаде состояний, но я просто думаю, что это может быть идеальный пример, который можно реализовать с помощью монады состояний. Итак, вот что я сделал:
getVal :: [Int] -> State [Int] Int
getVal poly = do
curState <- get
let lsb = last curState
modify $ chSt poly
return lsb
bitM :: State [Int] Int
bitM = getVal p
Это просто добавление к предыдущему сегменту кода вместе с import Control.Monad.State
в первом подобии программы. Когда я импортирую это в GHCI и проверяю вычисления состояний, я могу получить отдельные значения, как показано ниже:
[ghci] runState ( bitM ) s --> (0,[0,1,0,0])
[ghci] runState ( bitM >> bitM ) s --> (0,[0,0,1,0])
[ghci] runState ( bitM >> bitM >> bitM ) s --> (0,[1,0,0,1])
[ghci] runState ( bitM >> bitM >> bitM >> bitM) s --> (1,[1,1,0,0])
[ghci] runState ( bitM >> bitM >> bitM >> bitM >> bitM) s --> (0,[0,1,1,0])
[ghci]
Таким образом, как состояние обновляется правильно, так и возвращаемое значение также является правильным. Теперь я хочу создать функцию, подобную функции word
в предыдущей реализации, которая будет применять оператор >>
в bitM
s n
раз, чтобы мы могли создать массив word p s
. Я совершенно не понимаю, как это сделать. Обратите внимание, что я не хочу добавлять такие функции, как:
f1 = bitM
f2 = bitM >> bitM
f3 = bitM >> bitM >> bitM
...
Мне нужна одна функция, которой я передам n
, и она будет выполнять bitM
оценки последовательно n
раз, автоматически передавая состояние внутри последовательных вычислений, собирая результирующие значения и создавая в результате массив. Как мне это сделать? Я не могу понять, как это сделать. Любая помощь будет оценена!