Haskell/Arrows
外觀
< Haskell
箭頭是單子的推廣:每個單子都會產生一個箭頭,但並非所有箭頭都會產生單子。它們與單子有著相同的目的——為庫提供通用結構——但更為通用。特別是,它們允許部分靜態(獨立於輸入)或可能接受多個輸入的計算概念。如果你的應用程式可以用單子很好地工作,你最好堅持使用它們。但如果你正在使用一個非常類似於單子但不是單子的結構,那麼它可能就是一個箭頭。
讓我們首先了解箭頭的表示法。我們將使用最簡單的箭頭(函式)並構建一些玩具程式,其目的僅僅是為了熟悉語法。
開啟你的文字編輯器並建立一個 Haskell 檔案,比如 toyArrows.hs
{-# LANGUAGE Arrows #-}
import Control.Arrow (returnA)
idA :: a -> a
idA = proc a -> returnA -< a
plusOne :: Int -> Int
plusOne = proc a -> returnA -< (a+1)
這些是我們前兩個箭頭。第一個是箭頭形式的恆等函式,第二個稍微更有趣,是一個將輸入加一的箭頭。在 GHCi 中載入它,使用 -XArrows 擴充套件並檢視會發生什麼。
% ghci -XArrows toyArrows.hs ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.1, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base-1.0 ... linking ... done. Compiling Main ( toyArrows.hs, interpreted ) Ok, modules loaded: Main. *Main> idA 3 3 *Main> idA "foo" "foo" *Main> plusOne 3 4 *Main> plusOne 100 101
的確令人激動。到目前為止,我們已經在箭頭表示法中看到了三個新的構造
- 關鍵字
proc -<- 匯入的函式
returnA
既然我們已經知道如何將一個值加一,讓我們嘗試一個更困難的兩倍的嘗試:加二
plusOne = proc a -> returnA -< (a+1)
plusTwo = proc a -> plusOne -< (a+1)
一個簡單的做法是將 (a+1) 作為輸入提供給 plusOne 箭頭。注意 plusOne 和 plusTwo 之間的相似性。你應該注意到這裡有一個基本模式,它有點類似於:proc FOO -> SOME_ARROW <- (SOMETHING_WITH_FOO)
| 練習 |
|---|
|
我們當前的 plusTwo 實現實際上相當令人失望……它不應該只是 plusOne 兩次嗎?我們可以做得更好,但要做到這一點,我們需要引入 do 標記
plusTwoBis =
proc a -> do b <- plusOne -< a
plusOne -< b
現在在 GHCi 中試試這個
Prelude> :r Compiling Main ( toyArrows.hs, interpreted ) Ok, modules loaded: Main. *Main> plusTwoBis 5 7
你可以使用這個 do 標記構建任意長的序列
plusFive =
proc a -> do b <- plusOne -< a
c <- plusOne -< b
d <- plusOne -< c
e <- plusOne -< d
plusOne -< e
- FIXME:我不確定,但我相信這裡的意圖是展示使用這個 proc 標記與僅僅使用一個常規的 do 鏈的區別
| 本節是一個 存根。你可以透過 擴充套件它 來幫助 Haskell。 |