开发者

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 Rights) 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 Lefts 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 Lefts, 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 _ _ _ = []
 

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜