我一直在经历John Hughes' Programming with Arrows,我觉得直到以下使用mapA的例子我才能直言不讳:
>runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
[[0,0,0],[1,2,3],[4,5,6]]
其中runSF从定义为:
的StreamFunction箭头中提取流函数newtype SF a b = SF {runSF :: [a]->[b]}
延迟定义为:
delay x = SF (init . (x:))
SF是ArrowChoice的一个实例(声明mapA),因此是Arrow的实例。
mapA :: arr a b -> arr [a] [b]
delay :: SF a b
这样delay
只是将第二个参数加上第一个参数。
因此,mapA (delay 0)
应该返回一个SF箭头,该箭头需要[[a]]
并返回[[b]]
mapA (delay 0) :: SF [[a]] [[b]]
我希望"电路"这将导致:
数字标记过程的部分内容:
list x
,listcase
将发出Right(x, xs)
。对于空列表,listcase
将发出Left()
,终端案例。Right
的值将传递到下半部分。标记为Left
的值将传递给const[]
,这基本上会停止迭代。(x, xs)
,x
将传递给(delay 0)
,而xs
将传递回listcase
。(z, zs)
,传递给uncurry (:)
,将元组连接回列表。这是我对流程的理解,输入[[1,2,3],[4,5,6],[7,8,9]]
:
第一遍
Right ([1,2,3],[[4,5,6],[7,8,9]])
([1,2,3], [[4,5,6],[7,8,9]])
传递到下半部分(delay 0)
上调用[1,2,3]
,结果为[0,1,2]
。 [[4,5,6],[7,8,9]]
被传递回listcase
第二遍
Right ([4,5,6], [[7,8,9]])
([4,5,6], [[7,8,9]])
传递到下半部分(delay 0)
上调用[4,5,6]
,结果为[0,4,5]
。 [[7,8,9]]
被传递回listcase
第三次传递
Right ([7,8,9], [])
([7,8,9], [])
传递到下半部分(delay 0)
上调用[7,8,9]
,结果为[0,7,8]
。 []
会传回listcase
。第四遍
Left ()
,掉在地上。此时,我们到达第4部分,它取3的输出并将它们连接在一起。我们基本上构建了一个操作:
[0,1,2] : [[0,4,5] : [[0,7,8] : []]]
哪会给我们[[0,1,2],[0,4,5],[0,7,8]]
。
显然,我的上述流程是错误的。
如何调用runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]]
来[[0,0,0],[1,2,3],[4,5,6]]
?
答案 0 :(得分:8)
我发现这些例子很难理解。这里有两个列表 例如,外部列表是箭头操作的流,而 内部列表是mapA映射的内容。考虑一个更简单的例子,我们 现在可以忽略递归的情况。给定
runSF (mapA (delay 0)) [[1], [2]]
我们看到了第一步
listcase
箭头输入输入,为我们提供输出
[Right (1, []), Right (2, [])]
。每对的第一个元素
被喂入delay 0
箭头,而第二个元素被喂食
回到mapA f
。[1, 2] => delay 0
和[[], []] => mapA f
。
将[1,2]
提供到delay 0
会得到结果[0, 1]
,和
将空列表提供给mapA f
会产生更多空列表
[[], []]
。这两个结果被送到arr (uncurry (:))
,其行为类似于zipWith (:)
,
因为这些函数都映射在列表上,所以它连接两个输入
按元素列出。
[0, 1]
|
v
arr (uncurry (:)) => [ 0:[], 1:[] ] == [[0], [1]]
^
|
[[], []]
关键是要认识到使用arr
构建的所有内容都在运行
内部列表集,因此通过arr listcase
运行初始输入
不会产生Right ([1,2,3],[[4,5,6],[7,8,9]])
,但是
[Right (1, [2, 3]), Right (4, [5,6]), Right (7, [8,9])]
。
这是我尝试在图表中绘制它。
[Right (1, [2, 3]), Right (4, [5,6]), Right (7, [8,9])]
=======================================================
| [1, 4, 7] +-----------+ [0, 1, 4]
+----------+ | +----=--------->| delay |-----=------|
| listcase |---=------>| +-----------+ | +-------------------+
+----------+ | +-->| arr (uncurry (:)) |---> [[0,0,0],[1,2,3],[4,5,6]]
| | +-------------------+
| +-----------+ |
+-------=------>| mapA f |------=-----|
| +-----------+ |
| |
[[2,3],[4,5],[6,7]] [[0,0], [2,3],[4,5]]
* what will be
returned if you
trace it through
很抱歉,我不能把它画得更好。实际上,mapA
给出了转置视图
输入列表,因此您可以将mapA (delay 0)
视为操作
transpose . map (init . (0:)) . transpose
,因为init . (0:)
是。{1}}
delay
的定义。