You have some redundant cases in the definition of directions_. My use of the as-pattern below might be a little too much flourish, but technically it saves you a few list construction operations in putting b and c back on the front of your version of xs.

‡ Why I prefer pattern matching to guards

Precision

Efficiency

Consistency

Pattern matching repeats what is important about the value we're inspecting. The constructors and values we care about are directly on display, and the irrelevant portions are shown to be unimportant by naming them _. Consider the difference between these two fragments.

Now, are func1 and func2 equivalent? That depends on whether isSquare checks to see if you've been passed a Rectangle with equal length sides.

If you compile with -fwarn-incomplete-patterns GHC will tell you about partial pattern matches in your functions as well, but if you forget to include a guard you're on your own. E.g., my version of direction will not compile if you don't include the EQ case, your version will fail at runtime if you leave out s == 0.

In the example of direction, the guard version will perform three comparisons on s. The default definition of Ord defines all of the comparators (<, <=, &c) in terms of compare, so in the worst case you'll have to call compare three times to figure out which guard matches. In the case version compare is called only once and its result gets reused, potentially saving a lot of time if the implementation of compare were costly.

And lastly, having a set style and preference leads to consistency, which is always a boon to readability. I did it, therefore I do it.

\$\begingroup\$Note: though the last filterByList function is more elegant, it is unfortunately slower than the ugly one.\$\endgroup\$
– zigazouMar 4 '15 at 7:27

\$\begingroup\$Do you have a benchmark for that? Because it seems to be the other way around. Here is a gist compiling both versions with -O2 -ddump-simpl, you can see the Core for the elegant version turns into a tidy little foldr. There's a little teeny benchmark in there too, the elegant version runs >5 times faster.\$\endgroup\$
– bisserlisMar 4 '15 at 19:40

\$\begingroup\$Here are my outputs pastebin.com/5yxFDHJD As you can see the cost centre of filterByList increases when using the cleaner version.\$\endgroup\$
– zigazouMar 5 '15 at 8:04

\$\begingroup\$Dunno what to tell you, I'm using GHC 7.6.3 so it must be a compiler regression. I don't really understand your profiling output either because both reports reference graham.opt (lines 4 and 29) so it looks like you ran the same test twice.\$\endgroup\$
– bisserlisMar 5 '15 at 13:57

\$\begingroup\$You can download my tests here ouep.eu/pic/83125.zip just run make prof in the directory to compile and run the profiling. Concerning the profilings both saying graham.opt, it's only because I hand modified the same file to test the two functions. I am interested to see if it's a GHC regression from 7.6.3 to 7.8.3. Thanks :-)\$\endgroup\$
– zigazouMar 6 '15 at 6:01