我为left
类的流函数(SF)定义了right
/ ArrowChoice
方法,如下所示:
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]))
ghci中的一些测试看起来好像一切都很好:
λ> 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']
但与mapA
一起使用则说不然:
λ> 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]]
正确的答案应该是:
[[0,0,0],[1,2,3],[4,5,6]]
其中mapA定义为:
mapA :: ArrowChoice arr => arr a b -> arr [a] [b]
mapA f = arr listcase >>>
(arr (const []) ||| (f *** mapA f >>> arr (uncurry (:))))
答案 0 :(得分:7)
我认为您的ArrowChoice
实例不正确。
注意delay
函数接受一个流并替换第一个元素;关键的是,它并没有完全相同地对待所有元素。现在,请考虑您对Left
:
left (SF f) = SF $ map (either (\x -> Left . head $ f [x]) Right)
观察f
是整个流函数的内容,因此根据流的位置可能会有不同的行为。 left
函数然后创建一个新的流函数,在其流上映射一个同类函数,其中每个元素都通过(对于Right
s)或提升到单例输入流函数运行的列表。
而不是delay
,而是考虑以下函数:
skip = SF $ drop 1
这完全删除了流的第一个元素,并且由于left
每次在单个列表上独立运行其输入,这将完全过滤掉所有Left
个!可能不是你想要的。
相反,您需要执行诸如将流分区为其Left
和Right
组件之类的操作,将输入流功能应用于{{1}的整个流然后,将lefts和权利以原来相同的顺序合并在一起。
我得到的印象是你正在做这种运动,所以我不会通过简单地完全解决问题来破坏乐趣。但我会说我的代码确实在你的例子中给出了Left
。
如果您确实想查看我的测试代码,请点击下方。 (嘘,它藏起来了)
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 _ _ _ = []