流处理器的ArrowCircuit实例可能会阻塞



Control.Arrow.Operations.ArrowCircuit类用于:

可用于解释同步电路的箭头类型。

我想知道同步在这里意味着什么。我在维基百科上查了一下,他们说的是数字电子。我的电子设备很生疏,所以问题来了:所谓的异步流处理器的这样一个例子出了什么问题(如果有什么问题的话(:

data StreamProcessor a b = Get (a -> StreamProcessor a b) | 
Put b    (StreamProcessor a b) |
Halt
instance Category StreamProcessor where
id = Get ( x -> Put x id)

Put c bc . ab = Put c (bc . ab)
Get bbc . Put b ab = (bbc b) . ab
Get bbc . Get aab = Get $  a -> (Get bbc) . (aab a)
Get bbc . Halt = Halt
Halt . ab = Halt
instance Arrow StreamProcessor where
...
getThroughBlocks :: [a] -> StreamProcessor a b -> StreamProcessor a b
getThroughBlocks ~(a : input) (Get f)   = getThroughBlocks input (f a)
getThroughBlocks _input       putOrHalt = putOrHalt
getThroughSameArgBlocks :: a -> StreamProcessor a b -> StreamProcessor a b
getThroughSameArgBlocks = getThroughBlocks . repeat
instance ArrowLoop StreamProcessor where
loop Halt               = Halt
loop (Put (c, d) bdcd') = Put c (loop bdcd')
loop (Get f)            = Get $  b -> 
let 
Put (c, d) bdcd' = getThroughSameArgBlocks (b, d) (f (b, d))
in Put c (loop bdcd')
instance ArrowCircuit StreamProcessor where
delay b = Put b id

我认为这个解决方案对我们有效:我们希望someArrowCircuit >>> delay bsomeArrowCircuit延迟一个勾号,b先于它。很容易看出我们得到了我们想要的:

someArrowCircuit >>> delay b
= someArrowCircuit >>> Put b id 
= Put b id . someArrowCircuit
= Put b (id . someArrowCircuit)
= Put b someArrowCircuit

这样的阶级有法律吗?如果我把delay写下来没有错,同步如何与异步共存?

我所知道的与ArrowCircuit相关的唯一定律实际上是因果交换箭头中类似的ArrowInit类,它说delay i *** delay j = delay (i,j)。我很确定您的版本满足了这一点(它看起来是一个完全合理的实现(,但考虑到StreamProcessor不是同步的,这仍然感觉有点奇怪。

特别地,同步电路遵循单个输入产生单个输出的模式。例如,如果您有一个Circuit a b,并为它提供一个类型为a的值,那么您将得到一个并且只有一个输出b。";一个刻度延迟";CCD_ 13引入的延迟因此是一个输出乘以一个步长的延迟。

但异步电路的情况有点奇怪。让我们考虑一个例子:

runStreamProcessor :: StreamProcessor a b -> [a] -> [b]
runStreamProcessor (Put x s) xs = x : runStreamProcessor s xs
runStreamProcessor _ [] = []
runStreamProcessor Halt _ = []
runStreamProcessor (Get f) (x:xs) = runStreamProcessor (f x) xs
multiplyOneThroughFive :: StreamProcessor Int Int
multiplyOneThroughFive = Get $ x -> 
Put (x*1) $ Put (x*2) $ Put (x*3) $ Put (x*4) $ Put (x*5) multiplyOneThroughFive

这里,multiplyOneThroughFive为其接收的每个输入产生5个输出。现在,考虑multiplyOneThroughFive >>> delay 100delay 100 >>> multiplyOneThroughFive之间的差异:

> runStreamProcessor (multiplyOneThroughFive >>> delay 100) [1,2]
[100,1,2,3,4,5,2,4,6,8,10]
> runStreamProcessor (delay 100 >>> multiplyOneThroughFive) [1,2]
[100,200,300,400,500,1,2,3,4,5,2,4,6,8,10]

在电路中的不同点插入delay实际上导致我们产生不同数量的结果。事实上,整个电路似乎经历了5次延迟,而不仅仅是1次延迟。在同步环境中,这肯定是出乎意料的行为!

最新更新