具有多個通道的功能組合

模糊地講, Arrow 是一類構成類似函式的態射,具有連續組合和並行組合。雖然最有趣的是函式的泛化,但 Arrow (->) 例項本身已經非常有用。例如,以下功能:

spaceAround::Double -> [Double] -> Double
spaceAround x ys = minimum greater - maximum smaller
 where (greater, smaller) = partition (>x) ys

也可以用箭頭組合器編寫:

spaceAround x = partition (>x) >>> minimum *** maximum >>> uncurry (-)

這種組合最好用圖表視覺化:

                       ──── minimum ────
                   ╱           *            ╲
──── partition (>x) >>>        *        >>>  uncurry (-) ───
                   ╲           *            ╱
                       ──── maximum ──── 

這裡,

  • >>> 運算子只是一個翻轉普通 . 組成運算子的版本(也有對構成從右到左一 <<< 版)。它將資料從一個處理步驟傳輸到下一個處理步驟。

  • 外出的 表示資料流被分成兩個通道。就 Haskell 型別而言,這是通過元組實現的:

    partition (>x) :: [Double] -> ([Double], [Double])
    

    在兩個 [Double] 通道中分流,而

    uncurry (-) :: (Double,Double) -> Double
    

    合併了兩個 Double 頻道。

  • *** 是並行 組合運算元。它允許 maximumminimum 在不同的資料通道上獨立執行。對於函式,此運算子的簽名是

    (***) :: (b->c) -> (β->γ) -> (b,β)->(c,γ)
    

至少在 Hask 類別中(即在 Arrow (->) 例項中),f***g 實際上不會在不同的執行緒上平行計算 fg。不過,理論上這是可能的。