# Point-Free or Die: Part 1

Posted on August 6, 2016

This is the first post in a series about tacit programming and point-free syntax in Haskell and other languages. Be sure to check out Part 2!

For an initial understanding of tacit programming, consider that a synonym for tacit is quiet and an antonym is noisy. Code is noisy when it contains more information than we need to see. It’s quiet…when it doesn’t.

One way of producing tacit code is to write function definitions in a point-free style. As opposed to a point-ful definition, a point-free definition is tacit because it tells you about the function without mentioning one or more of its arguments.

Here is an example of a point-ful definition and its point-free equivalent:

``````lengths ls = map length ls

lengths = map lengths``````

They mean the same thing. Both definitions have this type:

``lengths :: Foldable t => [t a] -> [Int]``

In other words, `lengths` receives a list of foldable structures containing values of some generic type and returns a list of `Int`. That, is the list of lengths.

With differing syntax, the point-ful and point-free definitions communicate differently:

`lengths` receives a list of items and maps each to its `length`.

vs.

`lengths` is a map of `length`.

Consider the succinctness of the second version. It’s shorter and quicker to say, but understanding it requires that you know how `map` acts on the elements of a list.

## Calibrating Abstraction

Here’s another example:

``sum xs = foldr (+) 0 xs``

`sum` is a function that iterates over `xs` to add up its elements, starting from zero and proceeding from right to left.”

Or you could say:

``sum = foldr (+) 0``

`sum` is a right-fold of addition starting from zero.

When we leave out the `xs`, we communicate at a higher level of abstraction. We are no longer talking about what `sum` does, but what it is: a fold with certain properties.

Let’s combine these two functions to make a new one:

``totalNumber ls = foldr (+) 0 (map length ls)``

By substituting in our definitions for `sum` and `lengths`, we get

``totalNumber ls = sum (lengths ls)``

And of course, we can make this look a little more like Haskell by using `\$`.

``totalNumber ls = sum \$ lengths ls``

You could say it’s quieter with the `\$`, but it’s not point-free yet. `totalNumber` is defined in relation to its argument `ls`: “`totalNumber` receives a list of foldable structures and returns the `sum` of the `lengths` of those structures.”

But then, you could also just say, “`totalNumber` is the composition of `sum` and `lengths`.” How do we get there?

``````totalNumber ls =        sum \$ lengths ls
totalNumber ls =        sum . lengths \$ ls
totalNumber    = \ls -> sum . lengths \$ ls
totalNumber    =        sum . lengths``````

This is the process of eta-reduction: converting a point-ful definition to a point-free one. Here it takes three steps:

1. First, we notice that applying `sum` to `lengths ls` is equivalent to applying the composition `sum . lengths` directly to `ls`.
2. Next, we consider that `totalNumber` is a function that receives `ls` and simply applies an expression to it.
3. Finally, we drop the unnecessary lambda, removing `ls` from the definition.

Eta-reduction, also called eta-conversion is a simply mechanical process–which means computers can do it!

In fact, you don’t have to do any of your eta-reduction yourself. Haskell’s `pointfree` library can do it for you!