Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Haskell中无限期地在同一状态monad中线程化一个状态?_Haskell_State Monad - Fatal编程技术网

如何在Haskell中无限期地在同一状态monad中线程化一个状态?

如何在Haskell中无限期地在同一状态monad中线程化一个状态?,haskell,state-monad,Haskell,State Monad,从Haskell开始一直呆在州立大学Monad 因此,我试图了解Haskell中的状态单子,为了理解它,我正在编写一个生成PRBS序列的代码。对于感兴趣的人,在“伪随机序列和阵列”一文中对其进行了描述,doi可获得该文件的免费副本:10.1109/PROC.1976.10411 本质置换非常简单。你有一个移位寄存器和一个生成多项式。生成器多项式告诉您要获取移位寄存器的哪些位,并对模2求和以获取移位寄存器的MSB。在下一次迭代中,在执行右移位操作后,获取此计算出的MSB并将其固定到移位寄存器的MS

从Haskell开始一直呆在州立大学Monad

因此,我试图了解Haskell中的状态单子,为了理解它,我正在编写一个生成PRBS序列的代码。对于感兴趣的人,在“伪随机序列和阵列”一文中对其进行了描述,doi可获得该文件的免费副本:10.1109/PROC.1976.10411

本质置换非常简单。你有一个移位寄存器和一个生成多项式。生成器多项式告诉您要获取移位寄存器的哪些位,并对模2求和以获取移位寄存器的MSB。在下一次迭代中,在执行右移位操作后,获取此计算出的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]
这就是我想要的

当然,既然移位寄存器可以被认为是一个我们修改过的状态,我们就可以使用状态单子来实现这个目的。也许这是一个太简单的问题,无法了解状态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并不是真的必要。