Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
94 views26 pages

Constructing Applicative Functors

Haskell tutorial paper

Uploaded by

olwenntaron1707
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
94 views26 pages

Constructing Applicative Functors

Haskell tutorial paper

Uploaded by

olwenntaron1707
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

              

City Research Online

City, University of London Institutional Repository

Citation: Paterson, R. A. (2012). Constructing applicative functors. Paper presented at


the 11th International Conference, Mathematics of Program Construction, 25 - 27 Jun 2012,
Madrid, Spain.

This is the accepted version of the paper.

This version of the publication may differ from the final published
version.

Permanent repository link: http://openaccess.city.ac.uk/1141/

Link to published version:

Copyright and reuse: City Research Online aims to make research


outputs of City, University of London available to a wider audience.
Copyright and Moral Rights remain with the author(s) and/or copyright
holders. URLs from City Research Online may be freely distributed and
linked to.

City Research Online: http://openaccess.city.ac.uk/ [email protected]


Constructing Applicative Functors

Ross Paterson

City University London, UK

Abstract. Applicative functors define an interface to computation that


is more general, and correspondingly weaker, than that of monads. First
used in parser libraries, they are now seeing a wide range of applications.
This paper sets out to explore the space of non-monadic applicative func-
tors useful in programming. We work with a generalization, lax monoidal
functors, and consider several methods of constructing useful functors
of this type, just as transformers are used to construct computational
monads. For example, coends, familiar to functional programmers as ex-
istential types, yield a range of useful applicative functors, including left
Kan extensions. Other constructions are final fixed points, a limited sum
construction, and a generalization of the semi-direct product of monoids.
Implementations in Haskell are included where possible.

1 Introduction
This paper is part of a tradition of applying elementary category theory to the
design of program libraries. Moggi [16] showed that the notion of monad could be
used to structure denotational descriptions of programming languages, an idea
carried over to program libraries by Wadler [20]. It turns out that the monads
useful in semantics and programming can be constructed from a small number
of monad transformers also identified by Moggi [17].
Applicative functors [15] provide a more limited interface than monads, but
in return have more instances. All monads give rise to applicative functors,
but our aim is to explore the space of additional instances with applications
to programming. We are particularly interested in general constructions, with
which programmers can build their own applicative functors, knowing that they
satisfy the required laws. It is already known that applicative functors, unlike
monads, can be freely composed. We identify a number of further general con-
structions, namely final fixed points, a limited sum construction, a generalization
of semi-direct products of monoids, and coends (including left Kan extensions).
By combining these constructions, one can obtain most of the computational
applicative functors in the literature, with proofs of their laws. General con-
structions also clarify the relationships between seemingly unrelated examples,
and suggest further applications.
Elementary category theory provides an appropriately abstract setting for the
level of generality we seek. An idealized functional language corresponds to a type
of category with first-class functions (a cartesian closed category). Applicative
functors on such a category are equivalent to a simpler form called lax monoidal
2 Ross Paterson

functors, which are more convenient to work with. We can build up lax monoidal
functors in more general ways by ranging across several different categories, as
long as the end result acts on the category of our functional language, and is
thus applicative. Familiarity with the basic definitions of categories and functors
is assumed. The other notions used are mostly shallow, and will be explained
along the way.
In the next section, we introduce applicative and lax monoidal functors. The
rest of the paper describes the general constructions, illustrated with examples in
Haskell where possible. Two proof styles are used throughout the paper. When
making statements that apply to any category, we use standard commuting
diagrams. However many statements assume a cartesian closed category, or at
least a category with products. For these we use the internal language of the
category, which provides a term language with equational reasoning that will be
familiar to functional programmers.

2 Applicative Functors
The categorical notion of “functor” is modelled in Haskell with the type class
class Functor f where
fmap :: (a -> b) -> f a -> f b
Instances include a variety of computational concepts, including containers, in
which fmap modifies elements while preserving shape. Another class of instances
are “notions of computation”, including both monads and applicative functors,
in which terms of type F a correspond to computations producing values of type
a, but also having an “effect” described by the functor F , e.g. modifying a state,
possibly throwing an exception, or non-determinism. The requirement that F be
a functor allows one to modify the value returned without changing the effect.
The applicative interface adds pure computations (having no effect) and an
operation to sequence computations, combining their results. It is described by
a type class:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
If we compare this with the type class of monads:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
we see that pure corresponds to return; the difference lies in the sequencing
operations. The more powerful >>= operation available with monads allows the
choice of the second computation to depend on the result of the first, while in
the applicative case there can be no such dependency. Every monad can be made
an applicative functor in a uniform way, here illustrated with the Maybe monad:
Constructing Applicative Functors 3

instance Functor Maybe where


fmap f m = m >>= \ x -> return (f x)

instance Applicative Maybe where


pure = return
mf <*> mx = mf >>= \ f -> mx >>= \ x -> return (f x)
For functors that are also monads the monadic interface is often more convenient,
but here we shall be more interested in applicative functors that are not also
monads. A simple example is a constant functor returning a monoid [15]. Here
is that functor expressed in Haskell using the Monoid class, which defines an
associative binary operation <> with identity mempty:
newtype Constant a b = Constant a

instance Functor (Constant a) where


fmap f (Constant x) = Constant x

instance Monoid a => Applicative (Constant a) where


pure _ = Constant mempty
Constant x <*> Constant y = Constant (x <> y)

The more limited applicative interface has many more instances, some of which
will be presented in later sections. For example, the constrained form of sequenc-
ing offered by the applicative interface makes possible instances in which part
of the value is independent of the results of computations, e.g. parsers that pre-
generate parse tables [18]. Unlike monads, applicative functors are closed under
composition.
However many applications of monads, such as traversal of containers, can
be generalized to the applicative interface [15].

2.1 Lax Monoidal Functors


The applicative interface is convenient for programming, but in order to explore
relationships between functors we shall use an alternative form with a more
symmetrical sequencing operation:
class Functor f => Monoidal f where
unit :: f ()
mult :: f a -> f b -> f (a, b)
This interface, with identity and associativity laws, is equivalent to the applica-
tive interface—the operations are interdefinable:
pure x = fmap (const x) unit
a <*> b = fmap (uncurry id) (mult a b)

unit = pure ()
mult a b = fmap (,) a <*> b
4 Ross Paterson

If we uncurry the operation mult of the Monoidal class, we obtain an oper-


ation ~ : F a × F b → F (a × b). This suggests generalizing from products to
other binary type constructors, a notion known in category theory as a monoidal
category.
A monoidal category [13] consists of a category C, a functor ⊗ : C × C → C
and an object > of C, with coherent natural isomorphisms
λ:>⊗a∼ =a (left identity)
ρ:a⊗>∼ =a (right identity)
α : a ⊗ (b ⊗ c) ∼
= (a ⊗ b) ⊗ c (associativity)
A symmetric monoidal category also has
σ :a⊗b∼ =b⊗a (symmetry)
Both products and coproducts are examples of monoidal structures, and both
are also symmetric. Given a monoidal category hC, >, ⊗, λ, ρ, αi, the category
C op , obtained by reversing all the morphisms of C, also has a monoidal struc-
ture: hC op , >, ⊗, λ−1 , ρ−1 , α−1 i. The product of two monoidal categories is also
monoidal, combining the isomorphisms of the two categories in parallel.
Often we simply refer to the category when the monoidal structure is clear
from the context.
Some functors preserve this structure exactly, with >0 = F > and F a⊗0 F b =
F (a ⊗ b); a trivial example is the identity functor. Others, such as the product
functor × : A × A → A preserve it up to isomorphism:
1∼ =1×1
∼ (a1 × b1 ) × (a2 × b2 )
(a1 × a2 ) × (b1 × b2 ) =
We obtain a larger and more useful class of functors by relaxing further, requiring
only morphisms between the objects in each pair, thus generalizing the class
Monoidal above from products to any monoidal category.
A lax monoidal functor between monoidal categories hC, ⊗, >i and hC 0 , ⊗0 , >0 i
consists of a functor F : C → C 0 with natural transformations
u : >0 → F > (unit)
~ : F a ⊗0 F b → F (a ⊗ b) (multiplication)
such that the following diagrams commute:

>⊗F a
λ /Fa F a⊗>
ρ
/Fa
O O
u⊗F a Fλ F a⊗u Fρ
 
F >⊗F a / F (> ⊗ a) F a⊗F > / F (a ⊗ >)
~ ~

F a ⊗ (F b ⊗ F c)
F a⊗~
/ F a ⊗ F (b ⊗ c) ~
/ F (a ⊗ (b ⊗ c))

α Fα
 
(F a ⊗ F b) ⊗ F c / F (a ⊗ b) ⊗ F c / F ((a ⊗ b) ⊗ c)
~⊗F c ~
Constructing Applicative Functors 5

The first two diagrams state that u is the left and right identity respectively of
the binary operation ~, while the last diagram expresses the associativity of ~.

2.2 Weak Commutativity

Although the definition of a lax monoidal functor neatly generalizes the Monoidal
class, it lacks the counterpart of pure. We will also want an associated axiom stat-
ing that pure computations can be commuted with other computations. (There
is a notion of symmetric lax monoidal functor, but requiring the ability to swap
any two computations would exclude too many functors useful in computation,
where the order in which effects occur is often significant.)
Thus we define an applicative functor on a symmetric monoidal category C
as consisting of a lax monoidal functor F : C → C, with a natural transformation
p : a → F a (corresponding to the pure function of the Applicative class)
satisfying p> = u and p ◦ ~ = ~ ◦ p ⊗ p, plus a weak commutativity condition:

a⊗F b
p⊗F b
/ F a⊗F b ~
/ F (a ⊗ b)

σ Fσ
 
F b⊗a / F b⊗F a / F (b ⊗ a)
F b⊗p ~

We could also express the weak commutativity condition as a constraint on


functors with a tensorial strength, but here we shall avoid such technicalities by
assuming that function spaces are first-class types, with primitives to perform
application and currying, or in categorical terms that we are working in a carte-
sian closed category (ccc). In particular, if A is a ccc, any lax monoidal functor
F : A → A is also applicative. To show this, we make use of another advantage
of working in a ccc, namely that we can conduct proofs in the internal λ-calculus
of the category [12], in which variables of type a stand for arrows of A(1, a), and
we write f (e1 , . . . , en ) for f ◦ he1 , . . . , en i. The result is a convenient language
that is already familiar to functional programmers. When working in categories
with products we shall calculate using the internal language; when products are
not assumed we shall use diagrams.
.
In the internal language, we can define p : I → F with the counterpart of
the above definition of pure for any Monoidal functor:

p x = F (const x) u
6 Ross Paterson

The proof of weak commutativity is then a simple calculation in the internal


language:

F σ (p x ~ y) = F σ (F (const x) u ~ y) definition of p
= F (σ ◦ (const x) × id ) (u ~ y) naturality of ~
= F (σ ◦ (const x) × id ) (F λ−1 y) left identity
= F (id × (const x) ◦ σ) (F λ−1 y) naturality of σ
= F (id × (const x) ◦ σ ◦ λ−1 ) y functor
= F (id × (const x) ◦ ρ−1 ) y symmetry
= F (id × const x) (F ρ−1 y) functor
= F (id × const x) (y ~ u) right identity
= y ~ F (const x) u naturality of ~
= y ~ px definition of p

It is also known that lax monoidal functors in a ccc are equivalent to closed func-
tors [5], which resemble the Applicative interface, but again the lax monoidal
form is more convenient for defining derived functors.
Thus our strategy will be to construct a lax monoidal functor over the product
structure of a ccc, but we may construct it from constituents involving other
monoidal categories. As a simple example, we have seen that the product functor
× : A×A → A is lax monoidal, and we can compose it with the diagonal functor
from A to A × A (also lax monoidal) to obtain a lax monoidal functor from A
to A:
F a=a×a
though in this case the resulting functor is also monadic. In Section 5 we also
use auxiliary categories with monoidal structures other than products.

3 Fixed Points, Limits and Colimits

A standard example of a computational monad is the list monad, which may


be used to model backtracking. There is another lax monoidal functor on lists,
with a unit constructing infinite lists and multiplication forming the zip of two
lists [15]:

data ZipList a = Nil | Cons a (ZipList a)

instance Functor ZipList where


fmap f Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap f xs)

instance Monoidal ZipList where


unit = Cons () unit
mult (Cons x xs) (Cons y ys) = Cons (x,y) (mult xs ys)
mult _ _ = Nil
Constructing Applicative Functors 7

It turns out that this instance, and the proof that it satisfies the lax monoidal
laws, follow from a general construction. We can observe that ZipList is a fixed
point through the second argument of the binary functor F (a, b) = 1 + a × b.
That is, F is the functor Maybe ◦ ×, a composition of two lax monoidal functors
and therefore lax monoidal.
There are two canonical notions of the fixed point of a functor, the initial and
final fixed points, also known as data and codata. Initial fixed points can be used
to define monads; here we use final fixed points to define lax monoidal functors.
Recall that a parameterized final fixed point of a functor F : A × B → B consists
of a functor νF : A → B with an isomorphism c : F (a, νF a) ∼ = νF a and an
unfold operator [(·)] constructing the unique morphism satisfying

[(f )]
b / νF a
O
f c

F (a, b) / F (a, νF a)
F (a,[(f )])

If F is lax monoidal, we can define the unit and multiplication morphisms of a


lax monoidal structure on νF as two of these unfolds:
uνF =[(uF )]
> / νF >
O
uF c

F (>, >) / F (>, νF )
F (>,uνF )

~νF =[(~F ◦c−1 ⊗c−1 )]


νF a1 ⊗ νF a2 / νF (a1 ⊗ a2 )
O
c−1 ⊗c−1

F (a1 , νF a1 ) ⊗ F (a2 , νF a2 ) c

~F

F (a1 ⊗ a2 , νF a1 ⊗ νF a2 ) / F (a1 ⊗ a2 , νF (a1 ⊗ a2 ))
F (a1 ⊗a2 ,~νF )

In particular, for F = Maybe ◦ ×, this construction yields a lax monoidal functor


equivalent to ZipList above.
One can prove using fusion that this definition does indeed satisfy the lax
monoidal laws, but we shall prove a more general result instead.

3.1 Limits

Ignoring the parameter A for the moment, another way to define the final fixed
point of a functor F : B → B starts with the terminal object 1. Using with the
8 Ross Paterson

unique morphism !F 1 : F 1 → 1, we can define a chain of objects and morphisms:

··· / F3 1 / F2 1 /F1 /1
F 2 !F 1 F !F 1 !F 1

The final fixed point ν F is defined as the limit of this chain, an object with a
commuting family of morphisms (a cone) to the objects of the chain:

νF

" )/
/ F3 1 +/ /, 1
··· F2 1 F1
F 2 !F 1 F !F 1 !F 1

such that any other such cone, say from an object B, can be expressed as a
composition of a unique morphism B → νF and the cone from νF .
This construction is sufficient for final fixed points of regular functors like
ZipList, but for the general case we need to lift the whole thing to the category
Fun(A, B), whose objects are functors A → B, and whose morphisms are natural
transformations. Given a functor Φ on this category, we can repeat the above
construction in the functor category, starting with the constant functor 1:

νΦ

" )/
··· / Φ3 1 Φ2 1 /+ Φ 1 ,/ 1
2 Φ !Φ 1 !Φ 1
Φ !Φ 1

A standard result holds that limits in Fun(A, B) may be constructed from point-
wise limits in B [13, p. 112].
On the way to defining the final fixed point of Φ as a lax monoidal func-
tor, we wish to require that Φ preserve lax monoidal functors. To state this,
we need a specialized notion of natural transformation for lax monoidal func-
tors: a monoidal transformation between lax monoidal functors hF, ~, >i and
.
hF 0 , ~0 , >0 i is a natural transformation h : F → F 0 that preserves the lax
monoidal operations:

> F a⊗F b
h⊗h
/ F0 a ⊗ F0 b
0
u u
~ ~0
} !  
F> / F0 > F (a ⊗ b) / F 0 (a ⊗ b)
h h

Then given monoidal categories A and B, we can define a category Mon(A, B)


with lax monoidal functors as objects and monoidal transformations between
them as morphisms. Now suppose we have a diagram in Mon(A, B), e.g. the
chain
··· / F3 / F2 / F1 / F0
f2 f1 f0
Constructing Applicative Functors 9

We can construct a limit in Fun(A, B) (from pointwise limits in B):

F
t0
t3
/ F3 (/ /* F1 /+ F0
··· F2
f2 f1 f0

To extend F to a limit of this diagram in Mon(A, B), we want to define opera-


tions u and ~ on F such that the ti are monoidal transformations, i.e. satisfying
the following equations in B:

> F a⊗F b
ti ⊗ti
/ Fi a ⊗ Fi b
u ui
~ ~i
} !  
F> / Fi > F (a ⊗ b)
ti
/ Fi (a ⊗ b)
ti

These equations imply that u and ~ are mediating morphisms to the limits
in B, and thus uniquely define them. It remains to show that ~ is a natural
transformation, and that u and ~ satisfy the identity and associativity laws. Each
of these four equations is proven in the same way: we show that the two sides
of the equation are equalized by each ti , as a consequence of the corresponding
equation on Fi , and thus, by universality, must be equal. For example, for the
left identity law we have the diagram

>⊗F a
λ /Fa
O

>⊗ti
' w
ti

> ⊗ Fi a
λ / Fi a
O
u⊗F a ui ⊗Fi a Fi λ Fλ

Fi 7 > ⊗ Fi a / Fi (> ⊗ a)
~i f
ti ⊗ti ti


F >⊗F a / F (> ⊗ a)
~

The central panel is the left identity law for Fi , while the four surrounding panels
follow from the definitions of u and ~ and the naturality of λ and ti . Thus the
two morphisms > ⊗ F a → F a on the perimeter of the diagram is equalized by
ti . Since the universality of the limit implies that such a morphism is unique,
they must be equal. We have proven:
Proposition 1. If B is complete, then so is Mon(A, B).
Applying this to the chain of the fixed point construction, we have the im-
mediate corollary that the final fixed point of a higher-order functor Φ on lax
10 Ross Paterson

monoidal functors is a uniquely determined extension of the final fixed point


of Φ on ordinary functors. For example, ZipList is the final fixed point of the
higher-order functor Φ is defined by Φ Z a = Maybe (a × Z a).

3.2 Sums

The dual notion, colimits, is not as easily handled. We can construct sums in
special cases, such as adding the identity functor to another lax monoidal functor:

data Lift f a = Return a | Others (f a)

instance Functor f => Functor (Lift f) where


fmap f (Return x) = Return (f x)
fmap f (Others m) = Others (fmap f m)

instance Monoidal f => Monoidal (Lift f) where


unit = Return ()
mult (Return x) (Return y) = Return (x, y)
mult (Return x) (Others my) = Others (fmap ((,) x) my)
mult (Others mx) (Return y) = Others (fmap (flip (,) y) mx)
mult (Others mx) (Others my) = Others (mult mx my)

Here pure computations (represented by the identity functor and the constructor
Return) may be combined with mult, but are converted to the other functor if
either computation involves that functor.
Applying this construction to the constant functor yields a form of compu-
tations with exceptions that collects errors instead of failing at the first error [4,
15]:

type Except err a = Lift (Constant err) a

That is, in a computation mult e1 e2, after a failure in e1, the whole computa-
tion will fail, but not before executing e2 in case it produces errors that should
be reported together with those produced by e1.
The fixed point L ∼ = Lift (I × L) expands to non-empty lists combined with
a “long zip”, in which the shorter list is padded with copies of its last element
to pair with the remaining elements of the longer list, as suggested by Jeremy
Gibbons and Richard Bird1 :

data PadList a = Final a | NonFinal a (PadList a)

instance Functor PadList where


fmap f (Final x) = Final (f x)
fmap f (NonFinal x xs) = NonFinal (f x) (fmap f xs)
1
Personal communication, 5 July 2011.
Constructing Applicative Functors 11

instance Monoidal PadList where


unit = Final ()
mult (Final x) (Final y) = Final (x, y)
mult (Final x) (NonFinal y ys) =
NonFinal (x, y) (fmap ((,) x) ys)
mult (NonFinal x xs) (Final y) =
NonFinal (x, y) (fmap (flip (,) y) xs)
mult (NonFinal x xs) (NonFinal y ys) =
NonFinal (x, y) (mult xs ys)

A straightforward generalization is L = ∼ Lift (I × (F ◦ L)) for any lax monoidal


F , defining forms of long zip for various kinds of tree.
The Lift construction is able to combine computations in the identity func-
tor with those of another lax monoidal functor F because there is a monoidal
transformation between the two, namely the arrow pure. We can generalize:

Proposition 2. If J is an upper semi-lattice and B is a ccc with finite coprod-


ucts, a diagram ∆ : J → Mon(A, B) has a colimit.

Proof. Define a functor F by


X
Fa= Cj (∆j a)
j∈J
F f (Cj x) = Cj (f x)
.
where the Cj : ∆j → F are tagging injections (constructors) marking the terms
of the sum. Then we can define a lax monoidal structure on F as follows:

u = C⊥ u⊥
Cj a ~ Ck b = Cjtk (∆j≤jtk a, ∆k≤jtk b)

Naturality of ~ and the identity and associativity laws follow from simple cal-
culations. t
u

For example, in the case of Lift, J is a two-element lattice 0 ≤ 1, with


∆0 = I, ∆1 = F and ∆0≤1 = p.

4 Generalized Semi-direct Products


A pioneering instance of the applicative interface was the parser combinator
library of Swierstra and Duponcheel [18], which we here rehearse in a greatly
cut-down form.
These parsers are applied to the output of lexical analysis. Given a type
Symbol enumerating symbol types, parser input consists of a list of Tokens,
recording the symbol type and its text:
type Token = (Symbol, String)
12 Ross Paterson

For example, there might be a Symbol for numeric literals, in which case the
corresponding String would record the text of the number. Parsers take a list
of tokens and return either an error string or a parsed value together with the
unparsed remainder of the input:

newtype Parser a = P ([Token] -> Either String (a, [Token]))

This type is a monad (built by adding to an exception monad a state consisting


of a list of tokens), and therefore also an applicative functor. Parsers can be built
using primitives to peek at the next symbol, to move to the next token returning
the string value of the token read, and to abort parsing reporting an error:

nextSymbol :: Parser Symbol


advance :: Parser String
throwError :: String -> Parser a

In order to construct recursive descent parsers corresponding to phrases of a


grammar, one needs to keep track of whether a phrase can generate the empty
string, and also the set of symbols that can begin a phrase (its first set). Swierstra
and Duponcheel’s idea was to define a type containing this information about a
phrase, from which a deterministic parser for the phrase could be constructed:

data Phrase a = Phrase (Maybe a) (Map Symbol (Parser a))

The two components are:

– The type Maybe a indicates whether the phrase can generate the empty
string, and if so provides a default output value.
– The type Map Symbol (Parser a) records which symbols can start the
phrase, and provides for each a corresponding deterministic parser.

The Functor instance for this type follows from the structure of the type:

instance Functor Phrase where


fmap f (Phrase e t) = Phrase (fmap f e) (fmap (fmap f) t)

The idea, then, is to build a value of this type for each phrase of the grammar,
with the following conversion to a deterministic parser:

parser :: Phrase a -> Parser a


parser (Phrase e t)
| null t = def
| otherwise = do
s <- nextSymbol
findWithDefault def s t
where
def = case e of
Just x -> return x
Nothing -> throwError ("expected " ++ show (keys t))
Constructing Applicative Functors 13

A parser for a single symbol, returning its corresponding text, is


symbol :: Symbol -> Phrase String
symbol s = Phrase Nothing (singleton s advance)
Alternatives are easily built:
(<|>) :: Phrase a -> Phrase a -> Phrase a
Phrase e1 t1 <|> Phrase e2 t2 =
Phrase (e1 ‘mplus‘ e2) (t1 ‘union‘ t2)
In a realistic library, one would want to check that at most one of the alterna-
tives could generate the empty string, and that the first sets were disjoint. The
information in the Phrase type makes it possible to determine this check before
parsing, but we omit this in our simplified presentation.
Now the lax monoidal structure corresponds to the empty phrase and con-
catenation of phrases. A phrase αβ can generate the empty string only if both
the constituent phrases can, but the emptiness information for α also determines
whether the initial symbols of αβ include those of β in addition to those of α:
instance Monoidal Phrase where
unit = Phrase unit empty
mult (Phrase e1 t1) (~p2@(Phrase e2 t2)) =
Phrase (mult e1 e2) (union t1’ t2’)
where
t1’ = fmap (‘mult‘ parser p2) t1
t2’ = maybe empty (\ x -> fmap (fmap ((,) x)) t2) e1
In Haskell, a tilde marks a pattern as lazy, meaning it is not matched until its
components are used. It is used here so that Phrase values can be recursively
defined, as long as one avoids left recursion.
We might wonder whether this definition is an instance of a general con-
struction. We note that the Phrase type is a pair, and the first components
are combined using the lax monoidal operations on Maybe, independent of the
second components. This is similar to a standard construction on monoids, the
semi-direct product, which takes a pair of monoids hA, ∗, 1i and hX, +, 0i with
an action (·) : A×X → X, and defines a monoid on A×X, with binary operation

(a, x) (b, y) = (a ∗ b, x + (a · y))

and identity (1, 0). For example Horner’s Rule for the evaluation of a polynomial
an xn + · · · + a1 x + a0 can be expressed as a fold of such an operation over the list
[(x, a0 ), (x, a1 ), . . . , (x, an )], with the immediate consequence that the calculation
can be performed in parallel (albeit with repeated calculation of the powers of
x).
We shall consider a generalization of the semi-direct product on lax monoidal
functors, requiring
– a lax monoidal functor hF, ~, ui : hA, ⊗, >i → hB, ×, 1i
14 Ross Paterson

– a functor G : A → B with a natural family of monoids ⊕ : G a × G a → G a


and ∅ : 1 → G a.
– an operation o : G a × (F b × G b) → G (a ⊗ b) distributing over G:

∅oq =∅ (1)
(x ⊕ y) o q = (x o q) ⊕ (y o q) (2)

– an operation n : (F a × G a) × G b → G (a ⊗ b) distributing over G:

pn∅=∅ (3)
p n (x ⊕ y) = (p n x) ⊕ (p n y) (4)

also satisfying

(p n y) o r = p n (y o r) (5)

Proposition 3. Given the above functors and operations, there is a lax monoidal
functor hH, ~H , uH i : hA, ⊗, >i → hB, ×, 1i defined by

H a = F a × Ga
uH = (u, ∅)
(a, x) ~H (b, y) = (a ~ b, (x o (b, y)) ⊕ ((a, x) n y))

provided that n and o are left and right actions on G, i.e.

uH n z = z (6)
(p ~H q) n z = p n (q n z) (7)
x o uH = x (8)
x o (q ~H r) = (x o q) o r (9)

Proof. It follows from their definitions that H is a functor and ~H a natural


transformation. Next, we show that uH is the left and right identity of ~H :

uH ~H (b, y) = (1 ~ b, (∅ o (b, y)) ⊕ (uH n y)) definition of ~H , uH


= (1 ~ b, ∅ ⊕ y) equations (1) and (6)
= (b, y) monoid laws

(a, x) ~H uH = (a ~ 1, (x o uH ) ⊕ ((a, x) n ∅)) definition of ~H , uH


= (a ~ 1, x ⊕ ∅) equations (8) and (3)
= (a, x) monoid laws
Constructing Applicative Functors 15

Finally, we must show that ~H is associative:

((a, x) ~H (b, y)) ~H (c, z)


= (a ~ b ~ c, (((x o (b, y)) ⊕ ((a, x) n y)) o (c, z))⊕ definition of ~H
(((a, x) ~H (b, y)) n z))
= (a ~ b ~ c, ((x o (b, y)) o (c, z)) ⊕ (((a, x) n y) o (c, z))⊕ equation (2)
(((a, x) ~H (b, y)) n z))
= (a ~ b ~ c, (x o ((b, y) ~H (c, z)))⊕ (9), (5) and (7)
((a, x) n (y o (c, z))) ⊕ ((a, x) n ((b, y) n z)))
= (a ~ b ∗ c, (x o ((b, y) ~H (c, z)))⊕ equation (4)
((a, x) n (y o (c, z)) ⊕ ((b, y) n z)))
= (a, x) ~H ((b, y) ~H (c, z)) definition of ~H

t
u

In particular, Proposition 3 identifies the properties we need to establish to


demonstrate that Phrase is lax monoidal, and thus applicative.

5 Existentials and Coends

Many applicative functors are constructed using existential quantification, hiding


a private representation type. We shall consider the corresponding categorical
notion, called a coend.
Abbott, Altenkirch and Ghani [1] consider containers of the form

L c = ∃ m. K m → c

Here m is drawn from a set of shapes M (a discrete category), the functor


K : M → C assigns to each shape a set of positions within containers of that
shape, and the function provides a value for each of these positions. For example,
the shape of a list is a natural number n giving its length, which K maps to the
set of positions {0, 1, . . . , n − 1}, the indices of the list.
There are several ways that we can extend container functors to obtain useful
lax monoidal functors.
If we let M be the natural numbers plus an upper bound ω, and K n = {i |
i < n}, then L represents finite and infinite lists. We can define lax monoidal
operations:

u = (ω, const >)


(m, f ) ~ (n, g) = (m u n, hf, gi)

That is, u yields an infinite list, and ~ constructs a list of pairs, whose length is
the smaller of the lengths of the arguments. We recognize this functor as another
version of the ZipList functor defined in Section 3. More generally, if M has a
monoidal structure that is a lower semi-lattice, and K (m1 u m2 ) ⊆ K mi , then
the lax monoidal structure on L computes zips on containers.
16 Ross Paterson

A type comprising arrays of different dimensions can be represented using a


shape functor K satisfying K > ∼ = 1 and K (a ⊗ b) ∼= K a × K b. Then we can
define lax monoidal operations with with u constructing a scalar and ~ being
cartesian product:

u = (>, const ())


(m, f ) ~ (n, g) = (m ⊗ n, f × g)

We can approximate such multi-dimensional arrays using a Haskell existential


type (specified by using the quantifier keyword forall before the data construc-
tor):
data MultiArray a = forall i. Ix i => MA (Array i a)

instance Functor MultiArray where


fmap f (MA a) =
MA (array (bounds a) [(i, f e) | (i, e) <- assocs a])

The unit operation constructs a scalar, while mult forms the cartesian product
of two arrays:
instance Monoidal MultiArray where
unit = MA (array ((), ()) [((), ())])
mult (MA xs) (MA ys) =
MA (array ((lx, ly), (hx, hy))
[((i, j), (x, y)) | (i, x) <- assocs xs,
(j, y) <- assocs ys])
where
(lx, hx) = bounds xs
(ly, hy) = bounds ys
We could extend multi-dimensional arrays by adding a distinguished position,
i.e. a cursor within the container:

L c = ∃ m. K m × (K m → c)

When two arrays are combined with mult, their cursors are also paired to form
a cursor on the product array.
Another example arises in Elliott’s analysis of fusion [6], where folds are
reified using a type
data FoldL b a = FoldL (a -> b -> a) a
The type constructor FoldL is not a functor, because its argument a occurs
in both the domain and range of function types. Wishing to apply functorial
machinery to these reified folds, Elliott introduced a related type that could be
defined as a functor:
data WithCont z c = forall a. WC (z a) (a -> c)
Constructing Applicative Functors 17

instance Functor (WithCont z) where


fmap g (WC z k) = WC z (g . k)

Although FoldL is not a functor, it nevertheless has operations similar to unit


and mult. These can be described using a type class similar to Monoidal, but
without the Functor superclass:
class Zip z where
zunit :: z ()
zmult :: z a -> z b -> z (a, b)
The above type constructor FoldL is an instance:
instance Zip (FoldL b) where
zunit = FoldL const ()
zmult (FoldL f1 z1) (FoldL f2 z2) =
FoldL (\ (x,y) b -> (f1 x b, f2 y b)) (z1, z2)
This class is sufficient to define WithCont as a lax monoidal functor:
instance Zip z => Monoidal (WithCont z) where
unit = WC zunit (const ())
mult (WC t1 k1) (WC t2 k2) =
WC (zmult t1 t2) (\ (x,y) -> (k1 x, k2 y))

5.1 Left Kan Extensions


We now consider the general case. Kan extensions are general constructions that
have also found applications in programming. The right Kan has been used to
construct generalized folds on nested types [10], to fuse types [7], and to construct
a monad (the codensity monad) that can be used for program optimization [19,
8]. The lax monoidal functors discussed above are instances of the other variety,
the left Kan.
Kan extensions have an elegant description at the level of functors. Given a
functor K : M → C, the left and right Kan extensions along K are defined as
the left and right adjoints of the higher-order functor (◦K) that maps to each
functor C → A to a functor M → C [13]. That is, the left Kan extension a
functor T : M → A along K is a functor L : C → A with a universal natural
.
transformation η : T → L ◦ K:

M
K /C
η
=⇒
T
 L
A

For our purposes, it will be more convenient to use the standard pointwise
construction of the left Kan extension as a coend, corresponding to existen-
tial quantification in programming languages. For convenience, we assume that
18 Ross Paterson

the category A is cartesian closed, and that C is an A-category [11], i.e. that
the “hom-sets” of C are objects of A, with identity and composition morphisms
satisfying the usual laws. Using the more familiar notation ∃ in place of the in-
tegral sign favoured by category theorists, the left Kan extension of T : M → A
along K : M → C is the functor L : C → A defined by

L c = ∃ m. T m × C (K m, c)

The examples discussed above are instances of left Kan extensions:


– In the container example, T is the constant functor mapping to 1, and the
monoidal structure on M has > = ω and with ⊗ as minimum.
– In the example of arrays with cursors, T is identified with K.
– In the WithCont example, M is the subcategory of isomorphisms of A. T
can model any type constructor, as although type constructors (like FoldL
above) need not be functorial, they still preserve isomorphisms.
To state that L c is a coend is to say that there is an initial dinatural transfor-
mation ω : T m × C (K m, c) → L c. This dinaturality of ω is expressed by the
equation

ω (T h x, k) = ω (x, k ◦ K h)

That is, the existentially qualified type m is abstract: we can change the rep-
resentation without affecting the constructed value. The natural transformation
.
η : T → L ◦ K is defined as

η x = ω (x, id )

Initiality of ω means that a natural transformation from L is uniquely determined


by its action on terms of the internal language of the form ω (x, k). For example,
we can define the action of L on arrows as

L f (ω (x, k)) = ω (x, f ◦ k)

In order to make L lax monoidal, we shall assume that the functor K : M → C


is a colax monoidal functor, or equivalently a lax monoidal functor Mop → C op .
That is, there are natural transformations

s : K (a ⊗M b) → K a ⊗C K b
n : K >M → >C

such that the following diagrams commute:

K (> ⊗ a)
s / K>⊗Ka K (a ⊗ >)
s / Ka⊗K>

Kλ n⊗K a Kρ K a⊗n
   
Kao >⊗Ka Kao ρ
Ka⊗>
λ
Constructing Applicative Functors 19

K (a ⊗ (b ⊗ c))
s / K a ⊗ K (b ⊗ c) K a⊗s
/ K a ⊗ (K b ⊗ K c)

Kα α
 
K ((a ⊗ b) ⊗ c) / K (a ⊗ b) ⊗ K c / (K a ⊗ K b) ⊗ K c
s s⊗K c

In the special case where the monoidal structure on C is that of products, there is
only one choice for n, namely the unique arrow K > → 1. Moreover in that case
s : K (a ⊗ b) → K a × K b can be broken down into two components: s = hs1 , s2 i.
Proposition 4. If M and C are monoidal and A has finite products, K is colax
monoidal and T is lax monoidal, then L is lax monoidal, with
uL = ω (uT , nK )
ω (x1 , k1 ) ~L ω (x2 , k2 ) = ω (x1 ~T x2 , k1 × k2 ◦ sK )
This is a special case of Proposition 5, which we shall prove in the next
section.
A degenerate example has M as the trivial category with one object and one
morphism, so that T defines a monoid and K selects some object, with si = id .
This describes computations that write output and also read an environment,
but in which the output is independent of the environment:
L c = T × (K → c)
This applicative functor is a composition of two applicative functors that are
also monads, but the composition is not a monad.
Another simple case arises when M is a cartesian category, in which case an
arbitrary functor K : M → C can be made colax monoidal by setting si = K πi .
Thus we obtain the following Haskell version of the left Kan:2
data Lan t k c = forall m. Lan (t m) (k m -> c)
instance (Functor t, Functor k) => Functor (Lan t k) where
fmap f (Lan x k) = Lan x (f . k)
instance (Monoidal t, Functor k) => Monoidal (Lan t k) where
unit = Lan unit (const ())
mult (Lan x1 k1) (Lan x2 k2) =
Lan (mult x1 x2)
(\ y -> (k1 (fmap fst y), k2 (fmap snd y)))
Although this implementation has the form of a general left Kan extension, it is
limited to the Haskell category.
A richer example occurs in the modelling of behaviours of animations using
applicative functors by Matlage and Gill [14]. The basic functor comprises a
function over a closed interval of time, which can be modelled as pairs of times:
2
In fact the Functor instance requires no assumptions about t and k, and in the
Monoidal instance Zip t could replace Monoidal t.
20 Ross Paterson

data Interval = Between Time Time

instance Monoid Interval where


mempty = Between inf (-inf)
Between start1 stop1 <> Between start2 stop2 =
Between (min start1 start2) (max stop1 stop2)

We would like to represent continuous behaviours by a type ∃ i. K i → T , for a


functor K mapping pairs of times to closed intervals of time, with si mapping
from larger intervals to smaller by truncation. We cannot express this directly
in Haskell, which lacks dependent types, but we can approximate it with a type

data Behaviour a = B Interval (Time -> a)

provided we hide the representation and provide only an accessor function:

observe :: Behaviour a -> Time -> a


observe (B (Between start stop) f) t =
f (max start (min stop t))

Now this type can be made monoidal with the following definitions, which pre-
serve the abstraction:

instance Functor Behaviour where


fmap f (B i g) = B i (f . g)

instance Monoidal Behaviour where


unit = B mempty (const ())
mult b1@(B i1 f1) b2@(B i2 f2) =
B (i1 <> i2) (\ t -> (observe b1 t, observe b2 t))

The final functor used by Matlage and Gill can be obtained by adding constant
behaviour using Lift:

type Active = Lift Behaviour

Thus a value of type Active a is either constant or a function of time over a


given interval. A combination of such behaviours is constant only if both the
arguments were.

5.2 The General Case

Our final example is a generalization of the type used by Baars, Löh and Swier-
stra [3] to construct parsers for permutations of phrases, which we express as

data Perms p a = Choice (Maybe a) [Branch p a]


data Branch p a = forall b. Branch (p b) (Perms p (b -> a))
Constructing Applicative Functors 21

This implementation is too subtle to explain in full detain here, but the Perms
type is essentially an efficient representation of a collection of all the permuta-
tions of a set of elementary parsers (or actions, in other applications). The type
in the original paper is equivalent to restricting our version of the Perms type to
values of the forms Choice (Just x) [] and Choice Nothing bs, allowing a
single elementary parser to be added to the collection at a time. In contrast, the
mult methods allows the interleaving of arbitrary collections of actions, allowing
us to build them in any order.
The functor instances for these two types are straightforward:

instance Functor p => Functor (Perms p) where


fmap f (Choice def bs) =
Choice (fmap f def) (map (fmap f) bs)

instance Functor p => Functor (Branch p) where


fmap f (Branch p perm) = Branch p (fmap (f .) perm)

Assuming that p is lax monoidal, we will construct instances for Perms p and
Branch p. These types are mutually recursive, but we know that final fixed
points preserve applicative functors.
We define an operator *** as

(***) :: Monoidal f => f (a1 -> b1) -> f (a2 -> b2) ->
f ((a1,a2) -> (b1,b2))
p *** q = fmap (\ (f,g) (x,y) -> (f x, g y)) (mult p q)

This is an example of the construction of static arrows from applicative func-


tors [15]. Now, assuming that Perms p is lax monoidal, we can construct an
instance for Branch p as a generalized left Kan extension:

instance Monoidal p => Monoidal (Branch p) where


unit = Branch unit (pure id)
mult (Branch p1 perm1) (Branch p2 perm2) =
Branch (mult p1 p2) (perm1 *** perm2)

The instance for Perms p is constructed from the instance for Branch p as a
generalized semi-direct product, which builds all the interleavings of the two
collections of permutations:

instance Monoidal p => Monoidal (Perms p) where


unit = Choice unit []
mult (t1@(Choice d1 bs1)) (t2@(Choice d2 bs2)) =
Choice (mult d1 d2)
(map (‘mult‘ include t2) bs1 ++
map (include t1 ‘mult‘) bs2)
where
include :: Monoidal p => Perms p a -> Branch p a
include p = Branch unit (fmap const p)
22 Ross Paterson

To encompass examples such as this, we need a generalization of the left Kan.


Suppose the functor K factors through a monoidal category B:

>B
H J
=

M
K /C
η

T
 L
A
We also assume a natural operator
 : C(J a, J b) × C(J c, J d) → C(J (a ⊗ c), J (b ⊗ d))
(corresponding to *** above) satisfying unit and associativity laws:
Jλ◦f >=f ◦Jλ
Jρ◦>f =f ◦Jρ
J α ◦ f  (g  h) = (f  g)  h ◦ J α
The situation of ordinary left Kan extensions is the special case where J is the
identity functor and  is ⊗C . However in general we do not require that  be
a functor. The key example of a structure with such an operator is an enriched
premonoidal category, or “arrow” [2, 9].
Proposition 5. If M and B are monoidal, A has finite products, H is colax
monoidal and T is lax monoidal, then F = L ◦ J is lax monoidal, with
F a = ∃ m. T m × (J (H m) → J a)
F f (ω (x, k)) = ω (x, J f ◦ k)
uF = ω (uT , J nH )
ω (x1 , k1 ) ~F ω (x2 , k2 ) = ω (x1 ~T x2 , k1  k2 ◦ J sH )
Instead of proving this directly, we show that the functor G : Mop × M × A
defined by
G (m0 , m, a) = T m × (J (H m0 ) → J a)
is itself lax monoidal, and then use a general result about coends of lax monoidal
functors. To see that G is lax monoidal, we note that T is lax monoidal, so we
only need to show that the second component is. The left identity case is
F λ ◦ id  k ◦ J (nH × 1 ◦ sH ) = k ◦ J (λ ◦ nH × 1 ◦ sH ) left identity of 
= k ◦ J (H λ) left identity of H
The right identity case is similar. Associativity relies on the associativity of :
J α ◦ k1  (k2  k3 ◦ J sH ) ◦ J sH
= J α ◦ k1  (k2  k3 ) ◦ J (id × sH ◦ sH ) naturality of 
= (k1  k2 )  k3 ◦ J (α ◦ id × sH ◦ sH ) associativity of 
= (k1  k2 )  k3 ◦ J (sH × id ◦ sH ◦ H α) associativity of sH
Constructing Applicative Functors 23

Thus it suffices to show that coends preserve lax monoidal functors, which is our
final result.
Proposition 6. Given monoidal categories A and B and a ccc C, with a lax
monoidal functor G : Aop × A × B → C, then the coend F b = ∃ a. G (a, a, b) is
also lax monoidal, with
F b = ∃ a. G (a, a, b)
F f (ω x) = ω (G (id , id , f ) x)
uF = ω uG
ω x1 ~F ω x2 = ω (x1 ~G x2 )
Proof. It is a standard result that a parameterized coend such as F defines a
functor. Naturality of ~F follows from naturality of ~G :
F (f1 ⊗ f2 ) (ω x1 ~F ω x2 )
= F (f1 ⊗ f2 ) (ω (x1 ~G x2 )) definition of ~F
= ω (G (id , id , f1 ⊗ f2 ) (x1 ~G x2 )) definition of F
= ω (G (id , id , f1 ) x1 ~G G (id , id , f2 ) x2 ) naturality of ~G
= ω (G (id , id , f1 ) x1 ) ~F ω (G (id , id , f2 ) x2 ) definition of ~F
= F f1 (ω x1 ) ~F F f2 (ω x2 ) definition of F
Similarly the left identity law for F follows from the corresponding law for G:
F λ (uF ~F ω x) = F λ (ω uG ~F ω x) definition of uF
= F λ (ω (uG ~G x)) definition of ~F
= ω (G (id , id , λ) (uG ~G x)) definition of F
= ω (G (id , λ ◦ λ−1 , λ) (uG ~G x)) isomorphism
= ω (G (λ−1 , λ, λ) (uG ~G x)) dinaturality of ω
= ωx left identity of G
The right identity case is similar.
Finally, the associativity law for ~F follows from the associativity of ~G :
F α (ω x ~F (ω y ~F ω z))
= F α (ω x ~F ω (y ~G z)) definition of ~F
= F α (ω (x ~G (y ~G z))) definition of ~F
= ω (G (id , id , α) (x ~G (y ~G z))) definition of F
= ω (G (id , α ◦ α−1 , α) (x ~G (y ~G z))) isomorphism
= ω (G (α−1 , α, α) (x ~G (y ~G z))) dinaturality of ω
= ω ((x ~G y) ~G z) associativity of G
= ω (x ~G y) ~F ω z definition of ~F
= (ω x ~F ω y) ~F ω z definition of ~F
t
u
As a further example, we have the coend encoding of the final fixed point
ν F of a functor F : A × B → B:
νF a∼
= ∃ b. b × (b → F (a, b))
24 Ross Paterson

which is a coend of G (b0 , b, a) = b × (b0 → F (a, b)), and yields the same applica-
tive functor as discussed in Section 3.

6 Conclusion
We have established a number of general constructions of lax monoidal func-
tors, and therefore of applicative functors. In examples such as the permutation
phrases of Section 5.2, we showed that by combining these constructions we could
account for quite complex (and useful) applicative functors, avoiding the need for
specific proofs of their laws. By breaking the functors down into simple building
blocks, we have clarified their relationships, as well providing the tools to build
more applications. The next stage is to examine the possible combinations, and
to consider other constructions.

References
1. Michael Abbott, Thorsten Altenkirch, and Neil Ghani. Categories of containers.
In Andrew D. Gordon, editor, FoSSaCS, volume 2620 of LNCS, pages 23–38, 2003.
2. Robert Atkey. What is a categorical model of arrows? Electronic Notes on Theo-
retical Computer Science, 229(5):19–37, 2011.
3. Arthur I. Baars, Andres Löh, and S. Doaitse Swierstra. Parsing permutation
phrases. Journal of Functional Programming, 14(6):635–646, 2004.
4. Duncan Coutts. Arrows for errors: Extending the error monad, 2002. Unpublished
presentation at the Summer School on Advanced Functional Programming.
5. S. Eilenberg and G.M. Kelly. Closed categories. In S. Eilenberg, D. K. Harrison,
H. Röhrl, and S. MacLane, editors, Proceedings of the Conference on Categorical
Algebra, pages 421–562. Springer, 1966.
6. Conal Elliott. Denotational design with type class morphisms. Technical Report
2009-01, LambdaPix, 2009.
7. Ralf Hinze. Type fusion. In Dusko Pavlovic and Michael Johnson, editors, Pro-
ceedings of the Thirteenth International Conference on Algebraic Methodology And
Software Technology (AMAST ’10), volume 6486 of LNCS, pages 92–110. Springer,
2010.
8. Ralf Hinze. Kan extensions for program optimisation, or: Art and dan explain an
old trick. In Jeremy Gibbons and Pablo Nogueira, editors, Mathematics of Program
Construction, 2012.
9. John Hughes. Generalising monads to arrows. Science of Computer Programming,
37(1–3):67–111, May 2000.
10. Patricia Johann and Neil Ghani. A principled approach to programming with
nested types in Haskell. Higher-Order and Symbolic Computation, 22(2):155–189,
2009.
11. G. M. Kelly. Basic concepts of enriched category theory, volume 64 of London
Mathematical Society Lecture Note Series. Cambridge University Press, 1982.
12. J. Lambek and P. J. Scott. Introduction to Higher Order Categorical Logic. Num-
ber 7 in Cambridge Studies in Advanced Mathematics. Cambridge University
Press, Cambridge, 1986.
13. Saunders Mac Lane. Categories for the Working Mathematician. Springer, New
York, 1971.
Constructing Applicative Functors 25

14. Kevin Matlage and Andy Gill. Every animation should have a beginning, a middle,
and an end: A case study of using a functor-based animation language. In Rex Page,
Zoltán Horváth, and Viktória Zsók, editors, Proceedings of the 11th International
Conference on Trends in Functional Programming, volume 6546 of LNCS, pages
150–165. Springer, 2011.
15. Conor McBride and Ross Paterson. Applicative programming with effects. Journal
of Functional Programming, 18(1):1–13, 2008.
16. Eugenio Moggi. Computational lambda-calculus and monads. In Logic in Com-
puter Science, pages 14–23. IEEE Computer Society Press, 1989.
17. Eugenio Moggi. An abstract view of programming languages. Technical Report
ECS-LFCS-90-113, Laboratory for Foundations of Computer Science, University
of Edinburgh, 1990.
18. S. Doaitse Swierstra and Luc Duponcheel. Deterministic, error-correcting combina-
tor parsers. In John Launchbury, Erik Meijer, and Tim Sheard, editors, Advanced
Functional Programming, volume 1129 of LNCS, pages 184–207. Springer, 1996.
19. Janis Voigtländer. Asymptotic improvement of functions over free monads. In
Philippe Audebaud and Christine Paulin-Mohring, editors, Mathematics of Pro-
gram Construction, volume 5133 of LNCS, pages 388–403. Springer, 2008.
20. Philip Wadler. Comprehending monads. Mathematical Structures in Computer
Science, 2(4):461–493, 1992.

You might also like