2014-04-13 24 views
10

背景

我已經經歷約翰·休斯Programming with Arrows,我覺得我的一切直在我的頭上,直到使用地圖的下面的例子:mapA如何在Haskell中使用流函數箭頭?

>runSF (mapA (delay 0)) [[1,2,3],[4,5,6],[7,8,9]] 
[[0,0,0],[1,2,3],[4,5,6]] 

凡runSF提取流功能從定義爲流函數箭頭:

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

我會想到的是, 「電路」,這將導致是:

Diagram of Control Flow of mapA (delay 0)

凡過程號碼標籤部分:

  1. 對於任何非空list x,listcase將發出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. (delay 0)被稱爲上[1,2,3],res在[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. (delay 0)上調用[4,5,6],導致[0,4,5][[7,8,9]]被傳遞迴listcase
  • 第三通

    1. Right ([7,8,9], [])
    2. ([7,8,9], [])被傳遞給下部
    3. (delay 0)上調用[7,8,9],導致[0,7,8][]傳回listcase
  • 第四通

    1. Left(),掉在地上。

在這一點上,我們得到的第4部分,這需要3個輸出和concats它一起。我們主要打造的操作:

[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

那麼,顯然我的理解是關閉的,因爲延遲的類型是SF。本身不是一個函數。 – aftertommy

回答

7

我覺得這些例子很棘手。這個 示例中有兩個列表,外部列表是您的箭頭操作的流,而 內部列表是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操作,因爲init . (0:)delay的 定義。

+0

謝謝!是的,我現在意識到我完全忽略了那個列表被擡高到SF箭頭。您的圖表和簡單的演練對此非常有幫助。謝謝! – aftertommy

+0

終於......所有那些爛攤子都已經解剖到了核心...... :)許多人非常感謝!!!你描述了主要的錯誤 - 對'listcrasse'做了什麼錯誤的解釋(我沒有注意到'listcase'被提升爲'SF'只是將它自己映射到輸入列表的每個元素) - 在澄清這個事實之後,整理出來了.. – BarbedWire

相關問題