[Haskell-beginners] pattern match vs. pure function

Bastian Erdnüß earthnut at web.de
Wed Oct 20 03:10:03 EDT 2010


On Oct 20, 2010, at 2:23, Daniel Fischer wrote:

> On Wednesday 20 October 2010 01:23:49, Bastian Erdnüß wrote:
>> Suppose I would want to write a function rmap that acts like
>> 
>> rmap [f,g,h] x == [f x, g x, h x]
>> 
>> Do I gain any advantage or disadvantage (beside readability) from using
>> 
>> rmap = flip $ map . flip id
>> 
>> over
>> 
>> rmap []     _ = []
>> rmap (f:fs) x = f x : rmap fs x
>> 
>> ?
>> 
>> I could imagine Haskell can optimize the first version better since it
>> refers to the built in map function.  But beside that, does Haskell
>> struggle with the combinatory stuff in the first version?  Or does it
>> get optimized away?
> 
> Well, you can ask GHC what it does with the definitions.
> Let's compile
> 
> module RMap where
> 
> rmap :: [a -> b] -> a -> [b]
> rmap = flip $ map . flip id
> 
> recmap :: [a -> b] -> a -> [b]
> recmap [] _     = []
> recmap (f:fs) x = f x : recmap fs x
> 
> and look at the generated Core (obtained via -ddump-simpl).

Cool.  Didn't know that.

> The @ x_yz things are type annotations, otherwise Core is pretty close to 
> Haskell. It takes a bit to get used to reading Core, but it's not that 
> difficult (as long as the functions are short).

I see.  Well, still better then my hand writing ;-)

> First, without optimisations:
>
> [some good explinations]

Thanks!

> Now with optimisations. [...]
> 
> There, that looks much better than before (and for short lists, it performs 
> much better, but for long lists, the difference should be negligible).
> flip, ($) and (.) have been inlined and eliminated, what we get is
> 
> rmap fs x = map (\f -> f x) fs
> 
> , which is really nice. In fact, it's even nicer than what we got for 
> recmap, because the compiler knows map, there are rewrite rules, which can 
> produce much better code when the function is used, for example, it's 
> possible that the list of functions is completely eliminated and a use is 
> rewritten to a direct loop instead of allocating a list cell for each 
> function in the list. And it can profit from the rule
> 
> map f . map g = map (f . g)
> 
> which is much harder to detect for the direct recursion.

Good news, seems like Haskell has no problem with combinators.  As I hoped I could expect.

>> And how "expensive" are pattern matches on the other side, anyway?
> 
> Depends on the pattern, of course. Matching "oh" against [] is much cheaper 
> than matching "This is an expensive car" against
> 
> 'T':'h':'i':'s':' ':'a':'n':' ':'e':'x':'p':'e':'n':'s':'i':'v':'e':' 
> ':'p':'a':'t':'t':'e':'r':'n':' ':'m':'a':'t':'c':'h':_
> 
> But generally, pattern matching is quite cheap. The (well, one) advantage 
> of higher order functions like map is that they're easier to optimise when 
> they're used, given that somebody has taught the compiler how.

I understand.

Many thanks again for pointing out how I can test such things myself with -ddump-simple.

Cheers,
Bastian


More information about the Beginners mailing list