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 ***