繁体   English   中英

mapA如何在Haskell中使用Stream Function Arrow?

[英]How does mapA work with a Stream Function Arrow in Haskell?

背景

我一直在阅读约翰·休斯的“ 箭头编程” ,我觉得直到下面的使用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]]

我希望这会产生的“电路”是:

mapA的控制流程图(延迟0)

数字标记过程的一部分:

  1. 对于任何非空list xlistcase将发出Right(x, xs) 对于空列表, listcase将发出Left() ,终端大小写。
  2. 标记为Right值将传递到下部。 标记为Left值将传递给const[] ,这实际上会停止迭代。
  3. 使用输入(x, xs)x将传递给(delay 0) ,而xs将传递回listcase
  4. 3的输出将是(z, zs) ,它将被传递给uncurry (:) ,它将元组连接回列表。

这是我对流程的理解,输入[[1,2,3],[4,5,6],[7,8,9]]

  • 第一关

    1. Right ([1,2,3],[[4,5,6],[7,8,9]])
    2. ([1,2,3], [[4,5,6],[7,8,9]])传递到下部
    3. [1,2,3]上调用(delay 0) ,得到[0,1,2] [[4,5,6],[7,8,9]]被传递回listcase
  • 第二关

    1. Right ([4,5,6], [[7,8,9]])
    2. ([4,5,6], [[7,8,9]])传递到下半部分
    3. [4,5,6]上调用(delay 0) ,得到[0,4,5] [[7,8,9]]被传递回listcase
  • 第三关

    1. Right ([7,8,9], [])
    2. ([7,8,9], [])传递到下半部分
    3. [7,8,9]上调用(delay 0) ,得到[0,7,8] []传回listcase
  • 第四关

    1. 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]]

我发现这些例子很难理解。 在此示例中有两个列表,外部列表是箭头操作的流,而内部列表是mapA映射的内容。 考虑一个更简单的例子,所以我们现在可以忽略递归的情况。 特定

runSF (mapA (delay 0)) [[1], [2]]

我们看到了第一步

  1. 通过listcase箭头管道输入为我们提供输出[Right (1, []), Right (2, [])] 每对的第一个元素被馈送到delay 0箭头,而第二个元素被反馈到mapA f
  2. 所以,我们有[1, 2] => delay 0[[], []] => mapA f [1,2]delay 0给出结果[0, 1] ,并将空列表提供给mapA f产生更多空列表[[], []]
  3. 这两个结果被输入到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一样操作transpose . map (init . (0:)) . transpose transpose . map (init . (0:)) . transpose transpose . map (init . (0:)) . transpose ,因为init . (0:) init . (0:)delay的定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM