懒惰的模式

懒惰或无可辩驳的模式(用语法~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