I just learned about pointfree style in Haskell and how it can help tidy up the code and make it easier to read. But sometimes they can make the code a bit too terse.
So, when I should I always use pointfree style and at what scenarios should I absolutely avoid pointfree style in Haskell?
As already commented, it's a matter of taste and there will always be edge cases where both styles are equally suited (or, indeed, a partially-pointed version is best). However, there are some cases where it's clear enough:
If a pointed expression can be η-reduced just like that, it's usually a good idea to do it.
f x = g (h x)
should better be written
f = g . h
If you want to memoise some computation before accepting some function parameters, you must keep these parameters out of the scope. For instance,
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps x = a * x + b
where a, b = -- expensive calculation of regression coefficients,
-- depending on the `ps`
isn't optimal performance-wise, because the coefficients will need to be recomputed for every x
value received. If you make it point-free:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = (+b) . (a*)
where a, b = ...
this problem doesn't arise. (Perhaps GHC will in some cases figure this out by itself, but I wouldn't rely on it.)
Often though, it is better to make it pointed nevertheless, just not with an x
in the same scope as a
and b
but bound by a dedicated lambda:
linRegression :: [(Double, Double)] -> Double -> Double
linRegression ps = \x -> a * x + b
where a, b = ...
If the point-free version is actually longer than the pointed version, I wouldn't use it. If you need to introduce tricks to get it point-free like flip
and the Monad (a->)
instance and this doesn't even make it shorter, then it will almost certainly be less readable than the pointed version.