Haskell/Foldable

The  type class provides a generalisation of list folding (  and friends) and operations derived from it to arbitrary data structures. Besides being extremely useful,  is a great example of how monoids can help formulating good abstractions.

Deconstructing
This paragraph will introduce  as a replacement of. We will show how to implement the latter in terms of the former.

is quite a busy function − two binary functions on each side of the first function arrow, with types which use two variables each.

If we are going to generalise, it would be convenient to have something simpler to work with, or at least to be able to break it down into simpler components. What could those components be?

A rough description of list folding would be that it consists of running through the list elements and combining them with a binary function. We happen to know one type class which is all about combining pairs of values:. If we take  ...

... and make  and   ...

... we get, which is a simpler, specialised   in which we do not need to specify the combining function nor initial accumulator, as we simply use   (i.e.  ) and  :

captures the combine-all-elements aspect of  well enough, and covers a few of its use cases:

Neat − but surely we don't want to be restricted to folding with  instances only. One way to improve the situation a bit is by realising we can use  to fold a list with elements of any type, as long as we have a function to convert them to some   type:

That makes things more interesting already:

So far so good, but it seems that we are still unable to fold with arbitrary combining functions. It turns out, however, that any binary function that fits the  signature can be used to convert values to a   type! The trick is looking at the combining function passed to  as a function of one argument...

... and taking advantage of the fact that  functions form a monoid under composition, with   as   and   as. The corresponding  instance is available through the   wrapper from   :

We can now define...

... which makes a  function out of each element and composes them all:

If we apply that function to some  value...

...we finally recover. That means we can define  in terms of , a function which is much simpler and therefore easier to reason about. For that reason,  is the conceptual heart of , the class which generalises   to arbitrary data structures.

The class
Implementing  for a data structure requires writing just one function: either   or. , however, has a lot of other methods:

The extra methods are there so that more efficient implementations can be written if necessary. In any case, writing just  or   gives you all of the very useful functions listed above for free. And it gets even better: provides still more functions generalised to any , including, remarkably,  /.

Here is a quick demonstration of  using  :

Beyond providing useful generalisations,  and   suggest a more declarative way of thinking about folds. For instance, instead of describing  as a function which runs across a list (or tree, or whatever the data structure is) accumulating its elements with , we might say that it queries each element for its value and summarises the results of the queries using the   monoid. Though the difference may seem small, the monoidal summary perspective can help clarifying problems involving folds by separating the core issue of what sort of result we wish to obtain from the details of the data structure being folded.

List-like folding
includes the  method. That means any  data structure can be turned into a list; moreover, folding the resulting list will produce the same results as folding the original structure directly. A possible  implementation in terms of   would be :

reflects the fact that lists are the free monoid for Haskell types. "Free" here means any value can be promoted to the monoid in a way which neither adds nor erases any information (we can convert values of type  to   lists with a single element and back through   and   in a lossless way).

A related key trait of  is made obvious by. Since  for lists, if you are given a function defined as...

... it is always possible to recover the original list  by supplying   to. In this sense, lists are equivalent to their right folds. That implies folding with the  operations will unavoidably be a lossy operation if the data structure is more complex than a list. Putting it in another way, we can say that the list-like folds offered by  are less general than folds of the sort we have seen back in Other data structures (formally known as catamorphisms), which do make it possible to reconstruct the original structure.

More facts about
is slightly unusual among Haskell classes which are both principled and general-purpose in that it has no laws of its own. The closest thing is the following property, which strictly speaking is not a law (as it is guaranteed to hold whatever the instance is): given a monoid homomorphism ,

Switching from  to   can be advantageous, as it means applying   only to the result of the fold, rather than to the potentially many elements in the structure being folded.

If the  structure is a   as well, it also automatically holds that...

... and thus we get, after applying the second functor law and the property just above:

Though the presence of a method such as  might suggest that any   types should have   instances as well,   is not actually a superclass of. That makes it possible to give  instances to structures that, for whatever reason, cannot be  s. The most common example are the sets from. Element types for those sets must be instances of, and therefore their   function cannot be used as  , which has no additional class constraints. That, however, does not deny  an useful   instance.