I defined the left/right methods for stream functions (SF) of the ArrowChoice class as follows:
newtype SF a b = SF { runSF :: [a] -> [b] }
instance ArrowChoice SF where
left (SF f) =
SF $ map (either (\x -> Left . head $ f [x]) Right)
right (SF f) =
SF $ map (either Left (\x -> Right . head $ f [x]))
A few tests in ghci makes it seem like everything is fine:
λ> let lst = [Left 'c', Right 2, Left 'a', Right 3, Left 't']
λ> let foo = SF $ map toUpper
λ> let bar = SF $ map (+1)
λ> runSF (left foo) lst
[Left 'C',Right 2,Left 'A',Right 3,Left 'T']
λ> runSF (right bar) lst
[Left 'c',Right 3,Left 'a',Right 4,Left 't']
But using it with mapA says otherwise:
λ> let delay x = SF $ init . (x:)
λ> runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
[[0,0,0],[0,0,0],[0,0,0]]
The correct answer should be:
[[0,0,0],[1,2,3],[4,5,6]]
where mapA is defined as:
mapA :: ArrowChoice arr => arr a b -> arr [a] [b]
mapA f = arr listcase >>>
(arr (const []) ||| (f *** mapA f >>> arr (uncurry (:))))
I don’t think your
ArrowChoiceinstance is correct.Note that the
delayfunction takes a stream and replaces the first element; critically, it doesn’t treat all elements identically. Now, consider your definition ofLeft:Observe that
fis the guts of an entire stream function, and thus may behave differently depending on stream position. Theleftfunction then creates a new stream function that maps a homogeneous function over its stream, where each element is either passed through (forRights) or lifted to a singleton list on which the input stream function is run.Rather than
delay, consider instead the following function:This drops the first element of a stream entirely, and since
leftruns its input independently each time on a singleton list, this would filter out allLefts entirely! Probably not what you want.Rather, you need to do something like partition the stream into its
LeftandRightcomponents, apply the input stream function to the entire stream ofLefts, then merge the lefts and rights back together in the same sequence they were in originally.I get the impression that you’re doing this as some sort of exercise so I won’t spoil the fun by simply writing the solution out in full. But I will say that my code indeed gives
[[0,0,0],[1,2,3],[4,5,6]]on your example.If you do want to see my test code, it’s below. (shh, it’s hiding)