如何在Haskell中无限期地在同一状态monad中线程化一个状态?
从Haskell开始一直呆在州立大学Monad 因此,我试图了解Haskell中的状态单子,为了理解它,我正在编写一个生成PRBS序列的代码。对于感兴趣的人,在“伪随机序列和阵列”一文中对其进行了描述,doi可获得该文件的免费副本:10.1109/PROC.1976.10411 本质置换非常简单。你有一个移位寄存器和一个生成多项式。生成器多项式告诉您要获取移位寄存器的哪些位,并对模2求和以获取移位寄存器的MSB。在下一次迭代中,在执行右移位操作后,获取此计算出的MSB并将其固定到移位寄存器的MSB 在没有单子的情况下执行此操作的代码非常简单:如何在Haskell中无限期地在同一状态monad中线程化一个状态?,haskell,state-monad,Haskell,State Monad,从Haskell开始一直呆在州立大学Monad 因此,我试图了解Haskell中的状态单子,为了理解它,我正在编写一个生成PRBS序列的代码。对于感兴趣的人,在“伪随机序列和阵列”一文中对其进行了描述,doi可获得该文件的免费副本:10.1109/PROC.1976.10411 本质置换非常简单。你有一个移位寄存器和一个生成多项式。生成器多项式告诉您要获取移位寄存器的哪些位,并对模2求和以获取移位寄存器的MSB。在下一次迭代中,在执行右移位操作后,获取此计算出的MSB并将其固定到移位寄存器的MS
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]
这就是我想要的
当然,既然移位寄存器可以被认为是一个我们修改过的状态,我们就可以使用状态单子来实现这个目的。也许这是一个太简单的问题,无法了解状态monad,但我认为这可能是一个使用状态monad实现的完美例子。以下是我所做的:
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
因此,状态更新正确,返回的值也正确。现在,我想创建一个函数,就像前面实现中的函数字一样,它将在位上应用>>运算符n次,以便我们可以创建数组字ps。我完全不知道该怎么做。请注意,我不想放入一组函数,如:
f1 = bitM
f2 = bitM >> bitM
f3 = bitM >> bitM >> bitM
...
我想要一个传递n的函数,它将连续n次执行bitM求值,在连续计算中自动在内部传递状态,收集结果值,并作为结果创建一个数组。我该怎么做呢?我不知道该怎么做。任何帮助都将不胜感激 如果你稍微看一下,bitM>>bitM>>…>bitM可以被认为是一个操作列表,因此我们正在寻找Int->ma->[ma]或更简单的Int->a->[a],这只是复制的签名。我们最终会得到某种类型的东西
[State [Int] Int]
现在我们正在寻找[State[Int]Int]->State[Int][Int],或者更简单的[ma]->m[a],它恰好是序列。因此,您正在寻找
sequence . replicate n $ bitM
这恰好是ReplicateItem,它的类型为Int->ma->m[a]。如果您稍微看一下它,bitM>>bitM>…>bitM可以被认为是一个操作列表,因此我们正在寻找Int->ma->[ma]或更简单的Int->a->[a],这只是复制的签名。我们最终会得到某种类型的东西
[State [Int] Int]
现在我们正在寻找[State[Int]Int]->State[Int][Int],或者更简单的[ma]->m[a],它恰好是序列。因此,您正在寻找
sequence . replicate n $ bitM
正好是replicateM,它的类型是Int->ma->m[a]。序列。复制n就是复制n这正是我想要的!谢谢@尤里:谢谢。似乎我,而且我一直忘记自己的答案。\为了补充这个答案,您可能需要使用runState fmap last$replicItem bitM s,因为您想要的是最后一个操作的结果,而不是所有结果。@Teetoo:我想要一个传递n的函数,它将连续n次执行bitM求值,在连续计算中自动在内部传递状态,收集结果值,并作为结果创建一个数组。OP实际上对所有的结果都感兴趣,所以fmap last并不是真正必要的。复制n就是复制n这正是我想要的!谢谢@尤里:谢谢。似乎我,而且我一直忘记自己的答案。\为了补充这个答案,您可能需要使用runState fmap last$replicItem bitM s,因为您想要的是最后一个操作的结果,而不是所有结果。@Teetoo:我想要一个传递n的函数,它将连续n次执行bitM求值,在连续计算中自动在内部传递状态,收集结果值,并作为结果创建一个数组。OP实际上对所有结果都感兴趣,所以fmap last并不是真的必要。