Background
I've been going through John Hughes' Programming with Arrows, and I felt that I had everything straight in my head until the following example of using mapA:
>runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
[[0,0,0],[1,2,3],[4,5,6]]
Where runSF extracts the stream function from the StreamFunction arrow defined as:
newtype SF a b = SF {runSF :: [a]->[b]}
And delay is defined as:
delay x = SF (init . (x:))
SF is an instance of ArrowChoice (which declares mapA) and thus an instance of Arrow.
My Understanding
mapA :: arr a b -> arr [a] [b]
delay :: SF a b
such that delay
simply prepends its second argument with its first.
Thus, mapA (delay 0)
should return us an SF arrow that takes [[a]]
and returns [[b]]
mapA (delay 0) :: SF [[a]] [[b]]
I would expect that the "circuit" that this would result in is:
Where the numbers label parts of the process:
- For any non-empty
list x
,listcase
will emitRight(x, xs)
. For the empty list,listcase
will emitLeft()
, the terminal case. - Values tagged
Right
will be passed to the lower portion. Values taggedLeft
will be passed toconst[]
, which essentially stops the iteration. - With input
(x, xs)
,x
will be passed to(delay 0)
, whilexs
will be passed back through tolistcase
. - The output of 3 will be
(z, zs)
, which gets passed touncurry (:)
, which joins the tuple back into the list.
Here’s my understanding of the flow, with input [[1,2,3],[4,5,6],[7,8,9]]
:
First pass
Right ([1,2,3],[[4,5,6],[7,8,9]])
([1,2,3], [[4,5,6],[7,8,9]])
gets passed to the lower portion(delay 0)
is called on[1,2,3]
, resulting in[0,1,2]
.[[4,5,6],[7,8,9]]
is passed back tolistcase
Second pass
Right ([4,5,6], [[7,8,9]])
([4,5,6], [[7,8,9]])
gets passed to the lower portion(delay 0)
is called on[4,5,6]
, resulting in[0,4,5]
.[[7,8,9]]
is passed back tolistcase
Third pass
Right ([7,8,9], [])
([7,8,9], [])
gets passed to the lower portion(delay 0)
is called on[7,8,9]
, resulting in[0,7,8]
.[]
is passed back tolistcase
.
Fourth pass
Left ()
, dropped on the floor.
At this point, we get to part 4, which takes the output of 3 and concats it all together. We essentially build of an operation of:
[0,1,2] : [[0,4,5] : [[0,7,8] : []]]
Which would give us [[0,1,2],[0,4,5],[0,7,8]]
.
My Confusion
Clearly, my above flow is wrong.
How does calling runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
result in [[0,0,0],[1,2,3],[4,5,6]]
?