Reputation: 4993
I've read somewhere lately that pattern matching happens during run-time and not compile-time. (I am looking for the source, but can't find it at the moment.) Is it true? And if so, do guards in functions have the same performance?
Reading this was surprising to me because I used to think GHC was able to optimize some (probably not all) pattern match decisions during compile time. Does this happen at all?
A case for example:
f 1 = 3
f 2 = 4
vs
f' a | a == 1 = 3
| a == 2 = 4
Do f
and f'
compile to the same number of instructions (e.g. in Core and/or lower)?
Is the situation any different if I pattern match on a constructor instead of a value? E.g. if GHC sees that a function from a location is always invoked with one constructor, does it optimize that call in a way that eliminates the run-time check? And if so, can you give me an example showing what the optimization produces?
What is good to know about these two approaches in terms of performance?
When is one preferable performance-wise?
Upvotes: 12
Views: 1105
Reputation: 120711
Never mind patterns vs. guards, you might as well ask about if
vs. case
.
Pattern matching is preferrable to equality checks. Equality-checking is not really a natural thing to do in Haskell. Boolean blindness is one problem, but apart from that full equality check is often simply not feasible – e.g. infinite lists will never compare equal!
How much more efficient direct pattern matching is depends on the type. In case of numbers, don't expect much difference since those patterns are under the hood implemented with equality checks.
I generally prefer patterns – because they're just nicer and can be more efficient. Equality checks will be either just as expensive, or possibly more expensive, and are just un-idiomatic. Only use boolean evaluation when you have to, otherwise stick to patterns (which can be in guards too)!
Upvotes: 14