On Point-free Style

With a blog posting and then with some people sperging about the posting on Hacker News, I feel it’s time to write a post on the utility of point-free style, or “point-less” style as some call it.

One Hacker News poster, hristov, apparently reporting live from spergatory, had this to say:

First I would like to say that I am only learning Haskell, and have done nothing but toy programs thus far. But the point free style is something that I really do not like about Haskell. It makes code much more complicated for the dubious benefit of saving a couple of keystrokes.For example, take the code from the article:

This is without point free style: sum xs = foldr (+) 0 xs

And this is with: sum = foldr (+) 0

You have saved a total of 4 keystrokes. And made that line of code look really weird and hard to understand.

Thus, now when you look at code you cannot say at first glance how many arguments a function takes. The second line of code looks like sum takes 0 arguments. But you have to look more carefully at the definition of the function, and see that it uses foldr, and know that foldr takes three arguments, but here only two are defined, and then you figure out that someone is using point free style and then you figure out that sum, actually takes one argument that must be a list.

And this of course, is a simple example. Here we have a big clue in that the function is defined with zero arguments, and most functions take at least one argument, therefore the function probably uses the point free notation. But for a more complex and longer function, the point free style can very easily confuse someone reading the code.

So yeah, I think point free style is one of these annoying features of Haskell, that seem to be put in so that users of Haskell can pat themselves on the back and feel like they are very smart. But in the end it does not add much to the language and makes it much less accessible.

I have no idea whether this is a common form of misconfigured worldview.  Anyway, the Hacker News poster is right, and the blog poster is a bad person for confusing him.  (This shouldn’t be surprising, because blog posters who put a “Conclusion” section in their posts tend to be bad people.)  But where the Hacker News poster is right is where he says that using point-free style for top level definitions is pointless.  He’s sort of right.  He’s right because it is pointless.  The definition sum xs = foldr (+) 0 xs is generally more readable to everybody than the definition sum = foldr (+) 0.  It does no harm to write out the parameter, and it does make things more clear, because you’re advertising the arity of your function.  It helps anybody who’s new to your codebase.

But it’s not as bad as the Hacker News poster makes out, which is why his worldview is misconfigured. It’s not so bad when you see

sum :: Num a => [a] -> a
sum = foldr (+) 0

It’s not!  You have the type signature right there.  It’s basically standard to put type signatures on all your top-level functions.  And when you do that, it’s not so confusing.

Both the blog poster and the Hacker News poster are missing the more useful applications of point-free style, which is for the purpose of passing parameters to higher order functions and for avoiding horrible nests of parentheses.

For example, when solving Project Euler problem 62, the easiest way to tackle it was to chain a bunch of list manipulation operations together.

minimum
. head
. filter ((== 5) . length)
. concat
. map (groupBy ((==) `on` sort) . sortBy (compare `on` sort))
. groupBy ((==) `on` length)
. map (show . (^3))
$ [0..]

We have a ton of point-free examples there.  It is natural to use point-free style and function combinators for everything there.  If we didn’t, it would look like this:

minimum
 (head
  (filter (\ns -> length ns == 5)
          (concat
           (map (\xs -> groupBy (\x y -> sort x == sort y)
                                (sortBy (\x y -> compare (sort x)
                                                         (sort y))
                                        xs))
                (groupBy (\x y -> length x == length y)
                         (map (\k -> show (k^3)) [0..]))))))

How do you like that?  The parenthesis management is horrifying.  We could, then, make one small baby step towards point free style, and bring back the big chain of function composition, without touching the parameters we pass to map, groupBy, sortBy, and such.

minimum
. head
. filter (\ns -> length ns == 5)
. concat
. map (\xs -> groupBy (\x y -> sort x == sort y)
                      (sortBy (\x y -> compare (sort x)
                                               (sort y))
                              xs))
. groupBy (\x y -> length x == length y)
. map (\k -> show (k^3))
$ [0..]

An alternate baby step would have been first to make the parameters in point-free style.

minimum
 (head
  (filter ((== 5) . length)
          (concat
           (map (groupBy ((==) `on` sort)
                 . sortBy (compare `on` sort))
                (groupBy ((==) `on` length)
                         (map (show . (^3)) [0..]))))))

But really, we should just go for the best of both worlds.

Conclusion

The blog poster is dumb for making a blog posting about point-free style and demonstrating with top-level functions.  The real benefit of point-free style is for making function parameters and avoiding big gobs of syntax.  But don’t hate on the blog poster, because he doesn’t say wrong things.  The Hacker News poster is excused, because he’s a newbie to Haskell, and he’s reacting to the blog poster’s examples.  He also gets a pass because you can tell he’s generally an immature retard, which we know because he says, “You have saved a total of 4 keystrokes,” as if keystrokes was ever the point. Go count your lines of code, son, and when you’re done counting them, then maybe you get to make grandiose generalizations about the users of and an emergent property of a language you don’t understand.

4 Responses

  1. OJ says:

    Anyway, the Hacker News poster is right, and the blog poster is a bad person for confusing him.

    I think you’ll find the blog poster, ie. me, is discussing a feature of a language created by minds immesurable superior to yours and mine. I’m demonstrating its use, and showing how you can simplify, declutter and better understand your code by using it. I’m also using examples that are substantially simpler, because it’s targetted and the masses. You and the HN commenter you’re defending are focussing on arguably the least significant point that I was making. It’s obvious that the point of the post has sailed way over your head.

    Saying ridiculous things like “the blog post is a bad person” makes you look like an idiot. I’d recommend you think before you speak. Your post is misinformed, poorly structured, badly articulated and contains no solid arguments at all. But this doesn’t look like it’s out of the ordinary for you, as the rest of your posts seem to have the same qualities.

    This shouldn’t be surprising, because blog posters who put a “Conclusion” section in their posts tend to be bad people.

    I applaud you. You have succeeded in your efforts to come across as an idiot. Especially given that this very blog post contains a conclusion.

    As a final point: congratulations on receiving your first ever comment! After two months of writing dribble on the Internet and contributing to the noise rather than the signal, you’ve finally had someone respond.

    If you’re hoping for more comments in future, may I suggest you put some thought into writing something original. Attempt to come up with your own material rather than simply take shots at the efforts that others are making. Especially when you’re clearly punching above your weight.

  2. Alp says:

    You have a conclusion section in your blog post.

  3. stevefrench says:

    OJ, you spelled some words wrong.

    Therefore, you are wrong, and an idiot.

  4. Migs says:

    People who don’t understand irony posting comments