Applicative functors by Mark Seemann
An applicative functor is a useful abstraction. While typically associated with functional programming, applicative functors can be conjured into existence in C# as well.
This article series is part of a larger series of articles about functors, applicatives, and other mappable containers.
In a former article series, you learned about functors, and how they also exist in object-oriented design. Perhaps the utility of this still eludes you, although, if you've ever had experience with LINQ in C#, you should realise that the abstraction is invaluable. Functors are abundant; applicative functors not quite so much. On the other hand, applicative functors enable you to do more.
I find it helpful to think of applicative functors as an abstraction that enable you to express combinations of things.
In the functor article series, I mostly focused on the mechanics of implementation. In this article series, I think that you'll find it helpful to slightly change the perspective. In these articles, I'll show you various motivating examples of how applicative functors are useful.
- Full deck
- An applicative password list
- Applicative combinations of functions
- Test Data Generator
- Danish CPR numbers in F#
A Haskell perspective #
A normal functor maps objects in an 'elevated world' (like C#'s
IObservable<T>) using a function in the 'normal world'. As a variation, an applicative functor maps objects in an 'elevated world' using functions from the same 'elevated world'.
In Haskell, an applicative functor is defined like this:
class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b
This is a simplification; there's more to the
Applicative typeclass than this, but this should highlight the essence. What it says is that an applicative functor must already be a
Functor. It could be any sort of
 (linked list),
Either, and so on. Since
Functor is an abstraction, it's called
The definition furthermore says that in order for a functor to be applicative, two functions must exist:
pure is easy to understand. It simply 'elevates' a 'normal' value to a functor value. For example, you can elevate the number
42 to a list value by putting it in a list with a single element:
. Or you can elevate
Maybe by containing it in the
Just "foo". That is, literally, what
pure does for
 (list) and
<*> operator applies an 'elevated' function to an 'elevated' value. When
, this literally means that you have a list of functions that you have to apply to a list of values. Perhaps you can already see what I meant by combinations of things.
This sounds abstract, but follow the above list of links in order to see several examples.
An F# perspective #
Applicative functors aren't explicitly modelled in F#, but they're easy enough to add if you need them. F# doesn't have typeclasses, so implementing applicative functors tend to be more on a case-by-case basis.
If you need
list to be applicative,
pure should have the type
'a -> 'a list, and
<*> should have the type
('a -> 'b) list -> 'a list -> 'b list. At this point, you already run into the problem that
pure is a reserved keyword in F#, so you'll have to find another name, or simply ignore that function.
If you need
option to be applicative,
<*> should have the type
('a -> 'b) option -> 'a option -> 'b option. Now you run into your second problem, because which function is
<*>? The one for
list, or the one for
option? It can't be both, so you'll have to resort to all sorts of hygiene to prevent these two versions of the same operator from clashing. This somewhat limits its usefulness.
Again, refer to the above list of linked articles for concrete examples.
A C# perspective #
Applicative functors push the limits of what you can express in C#, but the equivalent to
<*> would be a method with this signature:
public static Functor<TResult> Apply<T, TResult>( this Functor<Func<T, TResult>> selector, Functor<T> source)
Here, the class
Functor<T> is a place-holder for a proper functor class. A concrete example could be for
public static IEnumerable<TResult> Apply<T, TResult>( this IEnumerable<Func<T, TResult>> selectors, IEnumerable<T> source)
As you can see, here you somehow have to figure out how to combine a sequence of functions with a sequence of values.
In some of the examples in the above list of linked articles, you'll see how this will stretch the capability of C#.
This article only attempts to provide an overview of applicative functors, while examples are given in linked articles. I find it helpful to think of applicative functors as an abstraction that enables you to model arbitrary combinations of objects. This is a core feature in Haskell, occasionally useful in F#, and somewhat alien to C#.
Next: Full deck.