4

我为类的流函数(SF)定义了left/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 (:))))
4

1 回答 1

7

我不认为你的ArrowChoice例子是正确的。

请注意,该delay函数接受一个流并替换第一个元素;至关重要的是,它不会对所有元素一视同仁。现在,考虑您的定义Left

left (SF f) = SF $ map (either (\x -> Left . head $ f [x]) Right)

请注意,这f是整个流函数的核心,因此可能会根据流的位置而有所不同。然后,该left函数创建一个新的流函数,该函数将同构函数映射到其流上,其中每个元素要么通过 (for Rights) 传递,要么提升到运行输入流函数的单例列表。

而不是delay,而是考虑以下函数:

skip = SF $ drop 1

这完全删除了流的第一个元素,并且由于left每次在单例列表上独立运行其输入,这将Left完全过滤掉所有 s!可能不是你想要的。

相反,您需要执行一些操作,例如将流分成其LeftRight组件,将输入流函数应用于 s 的整个Left,然后以它们最初的相同顺序将左侧和右侧合并在一起。

我的印象是你这样做是一种练习,所以我不会通过简单地完整地写出解决方案来破坏乐趣。但我会说我的代码确实给出[[0,0,0],[1,2,3],[4,5,6]]了你的例子。


如果您确实想查看我的测试代码,请参见下方。(嘘,藏起来了)

实例 ArrowChoice SF 在哪里
     左 (SF f) = SF $ \xs -> 让 (ls, rs) = partitionEithers xs
                               在合并 xs (f ls) rs
 
 合并(左_:xs)(l:ls)rs =左l:合并xs ls rs
 合并(右_:xs)ls(r:rs)=右r:合并xs ls rs
 合并_ _ _ = []
 

于 2011-08-01T05:46:10.620 回答