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

Zhi*_*gor 8 haskell functional-programming circuit stream-processing typeclass

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
Run Code Online (Sandbox Code Playgroud)

我们希望:因为我觉得这个解决方案为我们工作someArrowCircuit >>> delay bsomeArrowCircuit由一个刻度与延迟b从任何东西之前到来。很容易看出我们得到了我们想要的:

someArrowCircuit >>> delay b
= someArrowCircuit >>> Put b id 
= Put b id . someArrowCircuit
= Put b (id . someArrowCircuit)
= Put b someArrowCircuit
Run Code Online (Sandbox Code Playgroud)

这样的班级有什么法律规定吗?如果我没有记错的话delaysynchronous 是 如何 asynchronous 并存的

DDu*_*Dub 1

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

特别地,同步电路遵循单输入产生单输出的模式。例如,如果您有 aCircuit a b并为其提供类型为 的值a,那么您将得到一个且仅有一个输出b。因此,引入的“一滴答延迟”delay是一个输出一步的延迟。

但对于异步电路来说,事情有点奇怪。让我们考虑一个例子:

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
Run Code Online (Sandbox Code Playgroud)

在这里,multiplyOneThroughFive它为接收到的每个输入生成 5 个输出。multiplyOneThroughFive >>> delay 100现在,考虑和之间的区别delay 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]
Run Code Online (Sandbox Code Playgroud)

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