Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Situations to (not) use lazy pattern matching on tuples

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.

like image 680
Justin L. Avatar asked Mar 07 '15 06:03

Justin L.


3 Answers

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.

like image 188
Jon Purdy Avatar answered Nov 30 '22 03:11

Jon Purdy


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.

like image 25
danidiaz Avatar answered Nov 30 '22 02:11

danidiaz


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.

like image 27
dfeuer Avatar answered Nov 30 '22 04:11

dfeuer