Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy Pattern matching in Data.List

Tags:

haskell

What are the performance benefits of using ~ (lazy pattern matching) in Data.List's partition. Contrived examples of lazy pattern matching suggest that it is useful when the values inside the tuple constructor are never used (f (x,y) = 1). In partition (select, below), the lists ts, fs are always used (if the predicate p applied to x is True, or not). I'm sure this is a very well informed decision to use ~, but what is the point? Why not strict pattern matching?

partition               :: (a -> Bool) -> [a] -> ([a],[a])
{-# INLINE partition #-}
partition p xs = foldr (select p) ([],[]) xs

select :: (a -> Bool) -> a -> ([a], [a]) -> ([a], [a])
select p x ~(ts,fs) | p x       = (x:ts,fs)
                    | otherwise = (ts, x:fs)

(Note: I've already looked here! it doesn't answer the above question)

like image 474
Erin Dahlgren Avatar asked Sep 14 '12 17:09

Erin Dahlgren


People also ask

Is pattern matching faster than if else?

Python 3.10 match statements are faster at pattern matching sequences than equivalent if-statements. MUCH faster. The second functions runs 86% faster than the first.

How does Haskell pattern matching work?

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.

What is pattern matching syntax?

The pattern-matching algorithm uses a variety of techniques to match different kinds of expression. Data elements such as numbers, strings, booleans are matched by comparison: a pattern consisting of a single data element matches only that exact element.

What is pattern matching OCaml?

Pattern matching comes up in several places in OCaml: as a powerful control structure combining a multi-armed conditional, unification, data destructuring and variable binding; as a shortcut way of defining functions by case analysis; and as a way of handling exceptions.


1 Answers

The point is that with strict pattern matching, assembling of the result could only start when the end of the list to be partitioned has been reached, in particular, partition would not work at all for infinite lists.

With a strict pattern match, the argument must be evaluated to WHNF. That means the entire foldr of the tail must have finished before it is decided whether x is put in the first or the second component.

select p x (foldr (select p) ([],[]) (y:z:ws))
~> select p x (select p y (select p z (foldr (select p) ([],[]) ws)))

With a lazy pattern match, a pair is constructed immediately, with x as the first element of the appropriate component, and the rest of the two lists to be evaluated later, when needed.

like image 76
Daniel Fischer Avatar answered Sep 20 '22 18:09

Daniel Fischer