From what I can understand, lazy pattern matching on tuples is just deferring the resolving of the (,)
constructor...if we use the two fields immediately, is there really any downside? It will be resolved anyway...
Is there any reason to not use the lazy pattern match?
foo ~(x, y) = x + y
-- vs
foo (x, y) = x + y
When would you ever prefer to use the second?
EDIT: I'm specifically interested in the case where there will only be one pattern and the pattern will always match.
You wouldn’t want to use lazy pattern matching if you wanted to do any strict matching inside the lazy pattern. For example, given these definitions:
foo' (Just x, Just y) = Just (x + y)
foo' _ = Nothing
foo ~(Just x, Just y) = Just (x + y)
foo _ = Nothing
foo' (Just 5, Nothing)
gives Nothing
, but foo (Just 5, Nothing)
throws a runtime error—and additionally gives a compile-time warning that the _
case is redundant because the ~(…)
case is irrefutable.
It pretty much only makes sense to use lazy pattern matching when you know the pattern will always match, basically meaning that you’re only using single-constructor types such as (,)
throughout the lazy pattern.
One example is the State monad. The strict/lazy versions of the State monad are distinguished by how they pattern-match on the (value, state) pair during binds.
Strict State monad:
m >>= k = StateT $ \ s -> do
(a, s') <- runStateT m s
runStateT (k a) s
Lazy State monad:
m >>= k = StateT $ \ s -> do
~(a, s') <- runStateT m s
runStateT (k a) s'
The lazy pattern match in the lazy State monad lets you define strange programs like this one (taken from this blog post at Melding Monads):
pro :: State [Bool] ()
pro = do
pro
s <- get
put (True : s)
The program generates a lazy infinite list of True
values using "head recursion". The same program using the strict State monad would blow the stack before generating anything.
Laziness has performance costs. Sometimes, it has performance benefits. There's a reason the strict State
monad danidiaz mentions exists; delaying and delaying means eventually you may run out of memory, or get bad cache performance. You have to think about what's going on in each case. A good rule of thumb is that pattern matches should be strict unless there's a specific reason to make them lazy. When in doubt, or when performance is critical, try benchmarking and/or profiling with both ways.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With