Is (map f) == concatMap (map f . (:[]))?
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 ArrowChoice
instance is correct.
Note that the delay
function takes a stream and replaces the first element; critically, it doesn't treat all elements identically. Now, consider your definition of Left
:
left (SF f) = SF $ map (either (\x -> Left . head $ f [x]) Right)
Observe that f
is the guts of an entire stream function, and thus may behave differently depending on stream position. The left
function then creates a new stream function that maps a homogeneous function over its stream, where each element is either passed through (for Right
s) or lifted to a singleton list on which the input stream function is run.
Rather than delay
, consider instead the following function:
skip = SF $ drop 1
This drops the first element of a stream entirely, and since left
runs its input independently each time on a singleton list, this would filter out all Left
s entirely! Probably not what you want.
Rather, you need to do something like partition the stream into its Left
and Right
components, apply the input stream function to the entire stream of Left
s, 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)
instance ArrowChoice SF where left (SF f) = SF $ \xs -> let (ls, rs) = partitionEithers xs in merge xs (f ls) rs merge (Left _:xs) (l:ls) rs = Left l : merge xs ls rs merge (Right _:xs) ls (r:rs) = Right r : merge xs ls rs merge _ _ _ = []
精彩评论