Lazy, or irrefutable, patterns (denoted with the syntax ~pat) are patterns that always match, without even looking at the matched value. This means lazy patterns will match even bottom values. However, subsequent uses of variables bound in sub-patterns of an irrefutable pattern will force the pattern matching to occur, evaluating to bottom unless the match succeeds.
The following function is lazy in its argument:
f1 :: Either e Int -> Int
f1 ~(Right 1) = 42
and so we get
λ» f1 (Right 1)
42
λ» f1 (Right 2)
42
λ» f1 (Left "foo")
42
λ» f1 (error "oops!")
42
λ» f1 "oops!"
*** type mismatch ***
The following function is written with a lazy pattern but is in fact using the pattern's variable which forces the match, so will fail for Left arguments:
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 bindings are lazy, behave as irrefutable patterns:
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
Here act1 works on inputs that parse to any list of strings, whereas in act2 the putStrLn s1 needs the value of s1 which forces the pattern matching for [s1, s2], so it works only for lists of exactly two strings:
λ» act1
> ["foo"]
Done
λ» act2
> ["foo"]
*** readIO: no parse ***