The Control.Arrow.Operations.ArrowCircuit
class is for:
An arrow type that can be used to interpret synchronous circuits.
I want to know what synchronous means here. I looked it up on Wikipedia, where they are speaking of digital electronics. My electronics is quite rusty, so here is the question: what is wrong (if anything is) with such an instance for the so-called asynchronous stream processors:
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
I reckon this solution to work for us as: we want someArrowCircuit >>> delay b
to be someArrowCircuit
delayed by one tick with b
coming before anything from it. It is easy to see we get what we want:
someArrowCircuit >>> delay b
= someArrowCircuit >>> Put b id
= Put b id . someArrowCircuit
= Put b (id . someArrowCircuit)
= Put b someArrowCircuit
Are there any laws for such a class? If I made no mistake writing delay
down, how does synchronous live alongside asynchronous?
StreamProcessor
arrow isn't synchronous, which means you can't really talk about delaying by 1 tick. For instance, if you writedelay a >>> someSP
, it's not at all clear that the output is delayed 1 tick. IfsomeSP
has some extraGet
s, it could be entirely undelayed, and if it 20Put
s perGet
, then it could be delayed by 20 ticks. (Side note: thegetThroughBlocks
function is concerning — do the ArrowLoop laws hold here?) – Hyonhyoscinedelay a >>> someSP
to do?someSP >>> delay a
is understandable - we just push an extra value, no matter whether it'sGet
orPut
orHalt
to follow:arr ([0..] !!)
waits fori
and returnsi
, whereasarr ([0..] !!) >>> delay (-1)
spits-1
out first and then works as usual. – CannabingetThroughBlocks
? Are you speaking aboutgetThroughSameArgBlocks
inloop
? I haven't checked the definition forArrowLoop
laws - which one looks shaky? – Cannabindelay a >>> someSP
would theoretically providea
as "one tick's worth" of data tosomeSP
. In a synchronous circuit, this would allowsomeSP
to compute "one tick's worth" of output. Keep in mind thatarr
forStreamProcessor
does indeed create a synchronous circuit by virtue of it havingGet
s andPut
s precisely interleaved. However, if there were 5Put
s perGet
, then results would indeed by asynchronous to inputs, anddelay
would seem a bit strange. – HyonhyoscinegetThroughSameArgBlocks
. I don't know which law might break (if any), but it seems alarming to me that you're duplicating values from the input stream. – Hyonhyoscineloop
down? I tested my snippet on processors withconst
s as blocks - works fine. I will put a bit more thought into testing and write another comment. As fordelay
, let me sleep on that :). My electronics (or whatever this is) is quite rusty, so I am not quite following straight away. Thank you! – Cannabin