懶惰的模式

懶惰或無可辯駁的模式(用語法~pat 表示)是總是匹配的模式,甚至沒有檢視匹配的值。這意味著懶惰模式甚至會匹配底部值。但是,隨後使用繫結在無可辯駁模式的子模式中的變數將強制進行模式匹配,除非匹配成功,否則將評估為 bottom。

以下函式在其引數中是懶惰的:

f1 :: Either e Int -> Int
f1 ~(Right 1) = 42

所以我們得到了

λ» f1 (Right 1)
42
λ» f1 (Right 2)
42
λ» f1 (Left "foo")
42
λ» f1 (error "oops!")
42
λ» f1 "oops!"
###  type mismatch 

以下函式是使用惰性模式編寫的,但實際上是使用強制匹配的模式變數,因此 Left 引數將失敗:

f2 :: Either e Int -> Int
f2 ~(Right x) = x + 1

λ» f2 (Right 1)
2
λ» f2 (Right 2)
3
λ» f2 (Right (error "oops!"))
*** Exception: oops!
λ» f2 (Left "foo")
*** Exception: lazypat.hs:5:1-21: Irrefutable pattern failed for pattern (Right x)
λ» f2 (error "oops!")
*** Exception: oops! 

let 繫結是懶惰的,表現為無可辯駁的模式:

act1 :: IO ()
act1 = do
    ss <- readLn
    let [s1, s2] = ss :: [String]
    putStrLn "Done"

act2 :: IO ()
act2 = do
    ss <- readLn
    let [s1, s2] = ss
    putStrLn s1

這裡 act1 適用於解析任何字串列表的輸入,而在 act2 中,putStrLn s1 需要 s1 的值,這會強制 [s1, s2] 的模式匹配,因此它僅適用於兩個字串的列表:

λ» act1
> ["foo"]
Done
λ» act2
> ["foo"]
###  readIO: no parse