0% found this document useful (0 votes)
26 views

Constructing Polymorphic Programs With Quotient Types

This document summarizes a paper that proposes using quotient types to extend the theory of containers to allow for polymorphic programming over quotient data types. It introduces containers as a way to represent data types by their shapes and locations for storing data. The paper extends containers to quotient containers by allowing certain labelings of locations to be considered equivalent. This allows quotient data types like unordered pairs and cyclic lists to be represented. The paper defines a syntax for declaring quotient data types and writing polymorphic programs between them. It argues this captures all such polymorphic programs uniquely. The paper uses containers and previous work on generic programming with containers as a framework to develop these ideas.

Uploaded by

Star Monger
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)
26 views

Constructing Polymorphic Programs With Quotient Types

This document summarizes a paper that proposes using quotient types to extend the theory of containers to allow for polymorphic programming over quotient data types. It introduces containers as a way to represent data types by their shapes and locations for storing data. The paper extends containers to quotient containers by allowing certain labelings of locations to be considered equivalent. This allows quotient data types like unordered pairs and cyclic lists to be represented. The paper defines a syntax for declaring quotient data types and writing polymorphic programs between them. It argues this captures all such polymorphic programs uniquely. The paper uses containers and previous work on generic programming with containers as a framework to develop these ideas.

Uploaded by

Star Monger
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/ 15

Constructing Polymorphic Programs with Quotient

Types

Michael Abbott1 , Thorsten Altenkirch2 , Neil Ghani1 , and Conor McBride3


1 Department of Mathematics and Computer Science, University of Leicester
[email protected], [email protected]
2 School of Computer Science and Information Technology, Nottingham University
[email protected]
3 Department of Computer Science, University of Durham

[email protected]

Abstract. The efficient representation and manipulation of data is one of the


fundamental tasks in the construction of large software systems. Parametric
polymorphism has been one of the most successful approaches to date but, as of yet,
has not been applicable to programming with quotient datatypes such as unordered
pairs, cyclic lists, bags etc. This paper provides the basis for writing polymorphic
programs over quotient datatypes by extending our recently developed theory of
containers.

1 Introduction

The efficient representation and manipulation of data is one of the fundamental tasks
in the construction of large software systems. More precisely, one aims to achieve
amongst other properties: i) abstraction so as to hide implementation details and thereby
facilitate modular programming; ii) expressivity so as to uniformly capture as wide a
class of data types as possible; iii) disciplined recursion principles to provide convenient
methods for defining generic operations on data structures; and iv) formal semantics to
underpin reasoning about the correctness of programs. The most successful approach
to date has been Hindley-Milner polymorphism which provides predefined mechanisms
for manipulating data structures providing they are parametric in the data. Canonical
examples of such parametric polymorphic functions are the map and fold operations
which can be used to define a wide variety of programs in a structured and easy to reason
about manner.

However, a number of useful data types and associated operations are not expressible
in the Hindley-Milner type system and this has lead to many proposed extensions
including, amongst others, generic programming, dependent types (4), higher order
types (6) shapely types (9), imaginary types (13) and type classes. However, one area
which has received less attention is that of quotient types such as, for example, unordered
pairs, cyclic lists and the bag type. This is because the problem is fundamentally rather
difficult — on the one hand one wants to allow as wide a theory as possible so as to
encompass as many quotient types as possible while, on the other hand, one wants to
restrict ones definition to derive a well behave meta-theory which provides support for
key programming paradigms such as polymorphic programming etc.

This paper is, as far as we know, the first paper to give a detailed analysis of how to
program with quotient types in a polymorphic fashion. In particular we

• We provide a syntax for declaring quotient datatypes which encompasses a variety


of examples. This syntax is structural which we argue is essential for any theory of
polymorphism to be applicable.

• We show how the syntax of such a declaration gives rise to a quotient datatype.

• We provide a syntax for writing polymorphic programs between these quotient


datatypes and argue that these programs do indeed deserve to be called polymorphic.

• We show that every polymorphic function between our quotient datatypes is


represented uniquely by our syntax. That is, our syntax captures all polymorphic
programs in a unique manner.

To execute this program of research we extend our work on container datatypes (1; 2; 3).
Container types represent types via a set of shapes and locations in each shape
where data may be stored. They are therefore like Jay’s shapely types (9) but more
primitive as we discuss later. In previous papers cited above, we have shown how these
container types are closed under a wide variety of useful constructions and can also
be used as a framework for generic programming, eg they support a generic notion of
differentiation. (3).

This paper extends containers to cover quotient datatypes by saying that certain labellings
of locations with data are equivalent to others. We call these structures quotient
containers. As such they correspond to the step from normal functors to analytic functors
in Joyal’s work (11). However, our quotient containers are more general than analytic
functors as the allow infinite sets of positions to model coinductive datatypes. In addition,
our definition of the morphisms between quotient containers is new as is all of their
applications to programming. In addition, while pursuing the above program, we also
use a series of running examples to aid the reader. We assume only the most basic
definitions from category theory of category, functor and natural transformations. The
exception is the use of left Kan extensions for which we supply the reader with the
required information.

The paper is structured as follows. In section 2 we recall the basic theory of containers,
container morphisms and their application to polymorphic programming. We also discuss
the relationship between containers and shapely types. In section 3 we discuss how
quotient datatypes can be represented in container theoretic terms while in section
4 we discuss how polymorphic programs between quotient types can be represented
uniquely as morphisms between quotient containers. We conclude in section 5 with some
conclusions and proposals for further work.

2 A Brief History of Containers

Notation: Before we begin, some notation. We write N or the set of natural numbers
and if n ∈ N, we write n for the set {0, . . . , n − 1}. We assume the basic definitions of
category theory and if f : X → Y and g : Y → Z are morphisms in a category, we write
their composite g ◦ f : X → Z as is standard categorical practice. We write K1 for the
constantly 1 valued functor from any category to Sets. If A is a set and B is an A indexed
family of sets, we write Σ a:A.B(a) for the set {(a, b) | a ∈ A, b ∈ B(a)}. We write ! for the
empty map from the empty set to any other set. Injections into the coproduct are written
inl and inr.

This paper uses left Kan extensions to extract a universal property of containers which
is not immediately visible. We understand that many readers will not be familiar with
these structures so we supply all definitions and refer the reader to (12) for more details.
Their use is limited to a couple of places and hence doesn’t make the paper inaccessible
to the non-cogniscenti. Given a functor I : A → B and a category C , precomposition
with I defines a functor ◦ I : [B, C ] → [A , C ]. The problem of left Kan extensions is
the problem of finding a left adjoint to ◦ I. More concretely, given a functor F : A → C ,
the left Kan extension of F along I is written Lan I F defined via the natural isomorphism
[B, C ](LanI F, H) ∼
= [A , C ](F, H ◦ I)
One can use the following coend formula to calculate the action of a left Kan extension
when C = Sets and A is small
Z
(LanI F)X = B(IA, X) × FA
A∈A

What are Containers? Containers capture the idea that concrete datatypes consist of
memory locations where data can be stored. For example, any element of the type of lists
List(X) of X can be uniquely written as a natural number n given by the length of the
list, together with a function {0, . . . , n − 1} → X which labels each position within the
list with an element from X:
n:N , f : {0 . . . n − 1} → X .
We may think of the set {0, . . . , n − 1} as n memory locations while the function f
attaches to these memory locations, the data to be stored there. Similarly, any binary tree
tree can be uniquely described by its underlying shape (which is obtained by deleting the
data stored at the leaves) and a function mapping the positions in this shape to the data
thus:


• X
• x3 ∼
= x3 .
x1 x2 x2 x
1

More generally, we are led to consider datatypes which are given by a set of shapes S
and, for each s ∈ S, a set of positions P(s) which we think of as locations in memory
where data can be stored. This is precisely a container

Definition 1 (Container). A container (S . P) consists of a set S and and, for each s ∈ S,


a set of positions P(s).

Of course, in general we do not want to restrict ourselves to the category of sets since
we want our theory to be applicable to domain theoretic models. Rather, we would
develop our theory over over locally cartesian closed categories (7), certain forms of
fibrations such as comprehension categories (8) or models of Martin-L öf type theory —
our previous work (1; 2; 3) for such a development. However, part of the motivation for
this paper was to make containers accessible to the programming community where we
believe they provide a flexible platform for supporting generic forms of programming.
Consequently, we have deliberately chosen to work over Sets so as to enable us to get
our ideas across without an overly mathematical presentation.

As suggested above, lists can be presented as a container

Example 2 The list type is given by the container with shapes given by the natural
numbers N and, for n ∈ N, define the positions P(n) to be the set {0, . . . , n − 1}.

To summarise containers are our presentations of datatypes in the same way that data
declarations are presentations of datatypes in Haskell. The semantics of a container is an
endofunctor on some category which, in this paper, is Sets. This is given by

Definition 3 (Extension of a Container). Let (S . P) be a container. Its semantics, or


extension, is the functor TS.P : Sets → Sets defined by

TS.P (X) = Σ s ∈ S. (P(s) → X)

An element of TS.P (X) is thus a pair (s, f ) where s ∈ S is a shape and f : Ps → X is


a labelling of the positions over s with elements from X. Note that TS.P (X) really is a
functor since its action on a function g : X → Y sends the element (s, f ) to the element
(s, g ◦ f ). Thus for example, the extension of the container for lists is the functor mapping
X to

Σn : N. {0, . . . ..n − 1} → X .
Such pairs clearly bijectively correspond to lists.

The theory of containers was developed in a series of recent papers (1; 2; 3) which
showed that containers encompass a wide variety of types as they are closed under
various type forming operations such as sums, products, constants, fixed exponentiation,
(nested) least fixed points and (nested) greatest fixed points. Thus containers encapsulate
a large number of datatypes. So far, we have dealt with containers in one variable whose
extensions are functors on Sets. The extension to n-ary containers, whose extensions are
functors Setsn → Sets, is straightforward. Such containers consist of a set of shapes S,
and for each s ∈ S there are n position sets Pn (s). See the above references for details.

We finish this section with a more abstract presentation of containers which will be
used to exhibit the crucial universal property that they satisfy. This universal property
underlies the key result about containers. First, note that the data in a container S . P
can be presented as a functor P : S → Sets where here we regard the set S as a discrete
category and P maps each s to P(s). In future, we will switch between these two views
of a container at will. The semantic functor TS.P has a universal property given by the
following lemma.

Lemma 4. Let P : S → Sets be a container. Then TS.P is the left Kan extension of K1
along P

P
S Sets

K1
TS.P = LanP K1

Sets

Proof We calculate as follows

Z
(LanP K1 )X = Sets(Ps, X) × K1 s = Σ s : S. Sets(Ps, X) = TS.P (X)
s:S

where the first equality is the classic coend formula for coends, the second equality
holds as S is a discrete category and 1 is the unit for the product, and the last equality is
the definition of TS.P (X). 2

As we shall see, this universal property will be vital to our representation theorem.
2.1 Container Morphisms

Containers are designed for implementation. Thus, we imagine defining lists in a


programming language by writing something like
data List = (n : N . n)
although the type dependency means we need a dependently typed language. If we were
to do make such declarations, how should we program? The usual definition of lists
based upon initial/final algebras give rise naturally to recursive forms of programming.
We show that all polymorphic functions between containers are captured uniquely by
container morphisms.

To understand these container morphisms, consider the effect of the reverse function on
a list written in container form (n, f ). Its reversal must be a list and hence of the form
(n0 , f 0 ). In addition, n0 should only depend upon n since reverse is polymorphic and hence
shouldn’t depend upon the actual data in the list given by f . Thus there is a function
N → N. In the case of reverse, the length of the list doesn’t change and hence this is the
identity. To define f 0 which associates to each position in the output a piece of data, we
should first associate to each position in the output a position in the input and then look
up the data using f . Pictorially we have:
l1 l0
p0 p0 X
p1 p1
p2 p2
p3 p3

Here we start with a list l0 which has 4 positions and a labelling f function into X. The
result of reversing l0 is list with 4 positions with labelling function f 0 into X given by the
above composite. In general, we therefore define

Definition 5 (Container Morphisms). A morphism (A . B) → (C . D) consists of a


pair (u, f ) where u : A → C and, for each a ∈ A, a map f a : D(ua) → Ba. The category of
containers and container morphisms is written Cont

Example 6 The reverse program is given by the container morphism (Id, f n ) where the
function f n : {0, . . . , n − 1} → {0, . . . , n − 1} is defined by f n (i) = n − i − 1

Note how f n says that the data stored at the i0th cell after reversing a list is that data
stored at the n − i − 1’th cell in the input list. Here is an example of the tail function
tail:: List(X) → 1 + List(X). The shapes of the datatype 1+List(X) is 1+N with
the shapes above inl(∗) being empty while the shapes above inr(n) is the set {0, . . . , n −
1}. We therefore write this container as (1 + n : N . 0 + n).
Example 7 The tail function (u, f ) is given by the container morphism
(n : N . n) → (1 + n : N . 0 + n) is given by

u(0) = inl(∗) u(n + 1) = inr(n)

and, given n : N, define f 0 =! and f n+1 : n → n + 1 by f n+1 (i) = i + 1.

The last clause says that the i’th cell in the output of a nonempty list comes from the
i + 1’th cell in the input list. The reader may like to check their understanding at this
point by wondering what function is defined by setting f n+1 (i) = i in the above example.
We finish this section with two final points. First, a categorical re-interpretation of a
container morphism analogous to the categorical interpretation of a container A . B as a
presheaf B : A → Sets as in lemma 4.

Lemma 8. A morphism of containers (u, f ) : (A . B) → (C . D) is given by a functor


u : A → B and the following natural transformation
u
A C
⇐f

Set

Proof Since A and C are discrete categories, a functor is just a function. Since A is
discrete, the natural transformation is just a family of maps of the given form. 2

Finally, containers are more than just a tool to program with — they can also simplify
reasoning. For example, consider the problem of proving that reverse . reverse is the
identity. Using the usual recursive definition one soon runs into problems and one has
to strengthen the inductive hypothesis to include properties reflecting the interaction of
reverse and append. For the container definition, this problem is trivial as

(Id, fn ) ◦ (Id, f n ) = (Id, f n ◦ fn ) = (Id, Id)

2.2 From Container Morphisms to Polymorphic Functions and Back

Given a container morphism (u, f ) : (A . B) → (S . P) does (u, f ) really define a


polymorphic function TA.B → TS.P . And does it define all such polymorphic functions.
And in a unique manner? To answer these questions we have to describe mathematically
what a polymorphic function is. In the theory of program language semantics, covariant
datatypes are usually represented as functors while polymorphic functions between
covariant datatypes are represented by natural transformations (5). Other representations
of polymorphic functions are as terms in various polymorphic lambda calculi and via the
theory of logical relations. Various theoretical results show that these are equivalent so in
the following we take a polymorphic function to be a natural transformation.

Our key theorem is the following which ensures that our syntax for defining polymorphic
functions as container morphisms is flexible enough to cover all polymorphic functions.

Theorem 9. Container morphisms (A . B) → (C . D) are in bijection with natural


transformations TA.B → TC.D . Thus, the functor T : Cont → [Sets, Sets] defines a full
and faithful embedding of the category of containers into the category of endofunctors
over Sets.

Proof The proof is a special case of the one we give later for quotient types in
Theorem 19. Alternatively, see (2; 1) 2

Containers vs Shapely Types: In (10) and (9) shapely types (in one parameter) in
Sets are pullback preserving functors F : Sets → Sets equipped with a cartesian natural
transformation to the list functor. Essentially, this means there are natural maps FX →
List(X) which extracts the data from an element of FX and places it in a list thereby
obtaining a decomposition of data into shapes and positions similar to what occurs in
containers.

Note however that the positions in a list have a notion of order and hence a shapely type
is also equipped with an order on positions. Typically, when we declare a datatype we do
not want to declare such an ordering over it and, indeed, in the course of programming
we may wish to traverse a data structure with different orders. At a more theoretical level,
by reducing datatypes to lists a classification theorem such as Theorem 9 would reduce
polymorphic functions to polymorphic functions between lists but would not be able
to classify what these are. Containers do not impose such an order and instead reduce
datatypes to the more primitive idea of a family of positions indexed by a set of shapes.

3 Containers and Quotient Types

The purpose of this paper is to extend our previous results on containers to cover quotient
datatypes and polymorphic functions between them. In particular we want to

• Generalise the notion of container to cover as many quotient datatypes as possible


and thereby derive a syntax for declaring quotient datatypes.
• Define a notion of morphism between such generalised containers and thereby derive
a syntax for polymorphic programming with quotient types.

• Prove the representation theorem for these polymorphic programs thereby proving
that the quotient container morphisms really are polymorphic functions and that all
such polymorphic functions are captured by quotient container morphisms.

3.1 Unordered Pairs and Cyclic Lists

We begin with an example of unordered pairs. Note first that the type X × X is given by
the container (1 . 2). These are ordered pairs of elements of X. The type of unordered
pairs of X is written as X ⊗ X and is defined as X × X/ ∼ where ∼ is the equivalence
relation defined by
hx, yi ∼ hy, xi
Recall our analysis of the pair type was as one position, containing two shapes (1 . 2).
Lets call these positions p1 and p2 . An element of the pair type then consists of a labelling
for these positions, ie a function f : {p1 , p2 } → X for a set X. To move from unordered
pairs to ordered pairs is exactly to note that the labelling f should be regarded the same
as the labelling f ◦ swap where swap : {p1 , p2 } → {p1 , p2 } is the function sending p1 to
p2 and p2 to p1 . Thus

Example 10 The type of unordered pairs of elements of X is given by


({p1 , p2 } → X)/ ∼
where ∼ is the equivalence relation on {p1 , p2 } → X obtained by setting setting f ◦
swap ∼ f

Lets cement our intuitions by doing another example. A cyclic list is a list with no starting
point. Here is a cyclic list of length 5
x1

x5 x2

x4 x3

Can we represent cyclic lists in the same style as we used for unordered pairs? First recall
that lists were given by
List(X) ≡ Σn : N. {0, . . . ..n − 1} → X .
Now, in a cyclic list of length n, a labelling f : {0, . . . ..n − 1} → X should be equivalent
to the labelling f ◦ λ i.(i + k)mod n where k ∈ {0, . . . , n − 1}. Thus we may define

Example 11 The type of cyclic lists of elements of X is given by

CList(X) ≡ Σn : N. ({0, . . . ..n − 1} → X)/ ∼ .

where ∼ is the equivalence relation setting on {0, . . . ..n − 1} → X obtained by setting


f ∼ f ◦ λ i.(i + k)mod n where k ∈ {0, . . . , n − 1}.

The observant reader will have spotted that, in example 11, there is actually an
equivalence relation for each shape. However for clarity we leave this implicit. Also
we will henceforth write A → B/ ∼ rather than (A → B)/ ∼ for equivalence classes of
functions.

Examples 10 and 11 exemplify the kind of structures we wish to compute with, ie the
structures for which we want to find a clean syntax supporting program construction and
reasoning. In general they consist of a container as defined before with an equivalence
relation on labellings of positions. To ensure the equivalence relation is structural, ie
independent of data as one would expect in a polymorphic setting, the equivalence
relation is defined by identifying a labelling f : P(s) → X with the labelling f ◦ α where
α is one of a given set of isomorphisms on P(s). Hence we define

Definition 12 (Quotient Containers). A quotient container (S . P/G) is given by a


container (S . P) and, for each shape s ∈ S, a set G(s) of isomorphisms P(s) closed
under composition, inverses and containing the identity

Thus a quotient container has an underlying container and, every container as in


Definition 1 is a quotient container with an empty collection of isomorphisms. Another
way of describing the isomorphisms in a quotient container (S . P/G) is to say that for
each s ∈ S, G(s) is a subgroup of the automorphism group on P(s). Often we present
a quotient container (S . P/G) by defining, for each shape s ∈ S, the group G(s) to be
the smallest group containing a given set. However, the advantage of requiring G(s) to
be a group is that if we define f ∼G f 0 iff there is a g ∈ G(s) such that f = f 0 ◦ g,
then ∼G is automatically an equivalence relation and so we don’t have to consider its
closure. A more categorical presentation of quotient containers reflecting the presentation
of containers used in lemma 4 is the following

Lemma 13. A quotient container is exactly a functor P : S → Sets where every morphism
of S is both an endomorphism and an isomorphism

Proof Given a quotient container (S . P/G), we think of S as the category with objects
elements s ∈ S and, as endomorphisms of s, the set G(s). The functor P is then then
obvious functor mapping s to P(s). 2

Given a quotient container, (S . P/G), of course we want to calculate the associated


datatype or functor TS.P/G : Sets → Sets. As with the presentation of containers we do
this concretely and then more abstractly to uncover a hidden universal property.

Definition 14 (Extension of a Quotient Container). Given a quotient container, say


(S . P/G), its extension is the functor TS.P/G : Sets → Sets by

TS.P/G (x) = Σ s : S. (P(s) → X)/ ∼s

where ∼s is the equivalence relation on the set of functions P(s) → X defined by f ∼ f 0


if there is a g ∈ G(s) such that f 0 = f ◦ g

So a quotient container is like a container except that in the datatype it gives rise to, a
labelling f of positions with data is defined to be the same as the labelling f ◦ g obtained
by bijectively renaming the positions using g ∈ G(s) and then performing the labelling
f . The more abstract formulation is given by the next lemma which uses lemma 13 to
regard a quotient container (S . P/G) as a presheaf P : S → Sets

Lemma 15. Let P : S → Sets be a quotient container. Then TS.P/G is the left Kan
extension of K1 along P

P
S Set

K1
TS.P = LanP K1

Set

Proof We can calculate the left Kan extension as follows


R
(LanP K1 )X = s:S Sets(Ps, X) × K1 s

= Σ s : S. Sets(Ps, X)/ ∼

= TS.P (X)

where by first equality is the classic coend formula, the second is the reduction of coends
to colimits and the third is the definition of TS.P/G . This is because, the equivalence
relation ∼ in the coend has f ∼ f 0 iff there is a g : s → s such that f 0 = f ◦ P(g) where
f , f 0 : P(s) → X. This is exactly the definition of the extension of a quotient container. 2
The theory of containers thus generalises naturally to quotient containers as the same
formula of left Kan extension calculates both the semantics of a container and that of a
quotient container.

We finish this section on the presentation of quotient types with the example of finite bags
as promised. Bags of other sizes are of course a straightforward generalisation. given this
remark, we henceforth refer to finite bags as simply bags. The key intuition is that a bag
is like a set but elements may have multiple occurrences - one may thus define a bag as
Bag(X) = X → N. By putting all the elements of a bag in a list we get a representation
of the bag but of course there are many such representations since there is no order of
elements in the bag but there is in a list. Thus we get a bijection between bags and lists
quotiented out by all rearrangements of positions. Hence

Example 16 The bag type is the quotient container (S . P/G) where (S . P) is the
container for lists and, for n : N, we take G(n) to be the set of all isomorphisms on
the set {0, . . . , n − 1}

4 Programming with Quotient types

We have identified a class of quotient data structures and axiomatised them as


quotient containers. These quotient containers can be seen as datatype declarations in
a programming language and so we now ask how we program polymorphically with
these quotient containers.

Recall a container morphism (S . P) → (Q . R) consisted of a translation of shapes


u : S → Q and, for each s ∈ S, a map f s : R(us) → P(s) sending positions in the output to
positions in the input. If we now ask what is a map of quotient containers (S . P/G) →
(Q . R/H) its reasonable to require a map (u, f ) : (S . P) → (Q . R) of the underlying
containers which takes into account the respective quotients. There are two issues

• Since the maps f s : R(us) → P(s) are labellings, the quotient given by H says that
a quotient container morphism (u, f s ) is the same as another quotient container
morphism (u, f s0 ) if for each s ∈ S, there is an h ∈ H(us) such that f = f 0 ◦ h.
• Given a map f s : Q(us) → P(s) and a g ∈ G(s) then the labellings f and g ◦ f should
be regarded as equal as labellings of Q(us). Hence there should be an h ∈ H(us) such
that f ◦ h = g ◦ f .

Hence we define

Definition 17. A pre-morphism of quotient containers (S . P/G) → (Q . R/H) is given


by a morphism of the underlying containers (u, f ) : (S . P) → (Q . R) such that for each
g ∈ G(s), there is an h ∈ H(us) such that

fs
Q(us) P(s)

h g

Q(us) P(s)
fs

The morphisms (S . P/G) → (Q . R/H) are the premorphisms quotiented by the


equivalence relation

(u, f ) ∼ (u, f 0 ) iff for all s ∈ S, there exists h ∈ H(us) such that f s = fs0 ◦ h

Intuitively, the first condition is precisely the naturality of the quotient container
morphism while the second reflects the fact that labellings are defined upto quotient.
Is this a good definition of a polymorphic program between quotient containers? We
answer them two ways. On a theoretical level we show that all polymorphic programs
can be uniquely captured by such quotient container morphisms while on a practical
level we demonstrate a number of examples.

Lemma 18. The quotient container morphisms (S . P/G) → (Q . R/H) are in one-to-
one bijections with natural transformations K1 → TQ.R/H P where in the latter we regard
P : S → Sets as a presheaf as described in lemma 4.

Proof Such natural transformations are exactly S-indexed maps K1 (s) → TQ.R/H P(s)
which are natural in S. Thus we have maps

1 → Σ q : Q. R(q) → P(s)/ ∼H

which are natural in S. Such a family of S-indexed maps is exactly a map u : S → Q


and an S-indexed family of elements of R(us) → P(s)/ ∼ natural in S. An element of
R(us) → P(s)/ ∼ is clearly a an equivalence class of functions while the naturality
corresponds to the commuting diagram above 2

Theorem 19. Quotient container morphisms are in one-to-one bijection with natural
transformations between their extensions. Hence there is a full and faithful embedding
T : QCont → [Sets, Sets]

Proof Natural transformations TS.P/G → TQ.R/H are by lemma 15 exactly natural


transformations LanP K1 → LanR K1 . By the universal property of Kan extensions
given at the beginning of section 2, these are in one-to-one bijection with natural
transformations K1 → TQ.R/H P which by lemma 18 are in one-to-one bijection with
quotient container morphisms (S . P/G) → (Q . R/H) 2

Notice the key role of the left Kan extension here. It identifies a universal property of the
extension of a quotient container which is exactly what is required to prove Theorem 19.
Also note that Theorem 9 is a corollary as there is clearly a full and faithful embedding
of Cont into QCont

We now finish with some examples. Firstly, if (S . P/G) is a container and for each s ∈ S
the group G(s) is a subgroup of H(s), then there is a morphism of quotient containers
(S . P/G) → (S . P/H). Thus

Example 20 The canonical maps List(X) → CList(X) → Bag(X) are polymorphic as,
for a given n ∈ N, they arise as container morphisms from the inclusions of the singleton
group into the group of functions {λ i.i + kmodn|k ∈ {0, . . . , n − 1}} and of this group
into the group of all isomorphisms on {0, . . . , n − 1}

Example 21 Every datatype given by a quotient container (S . P/G) has a map


operation which is given by the action of functor TS.P/G on morphisms

Example 22 We can extend the operation of reversing a list to a reverse on cyclic


lists. One simply needs to check the commutation condition that for each size n and
k ∈ {0, . . . , n − 1}, there is a k 0 such that

λ i.(i + k)modn ◦ λ i.n − i − 1 = λ i.n − i − 1 ◦ λ i.(i + k 0 )modn

Of course we simply take k 0 = n − k − 1

In general this shows how simple our theory is to apply in practise. We simply have one
condition to check!

5 Conclusions and Further Work

We have provided a synthesis of polymorphism with quotient datatypes in such as way


as to facilitate programming and reasoning with such quotient structures. This work
is based upon an extension of our previous work on containers which, going further
than shapely types, present datatypes via a collection of shapes and, for each shape, a
collection of positions where data may be stored. The treatment of quotient datatypes
is structural in that the quotient is determined by a collection of isomorphisms on
these position sets which induce a quotient on the labellings of positions with data.
On top of this presentation of datatypes, we have provided a means for programming
with such structures by defining morphisms of quotient containers. These are essentially
morphisms of the underlying containers which respect the relevant quotients. This simple
axiomatisation is proven correct in that we show that these morphisms determine exactly
the polymorphic programs between these quotient data structures.

As for further work, we believe containers are an excellent platform for generic program
and we wish to develop this application of containers. With specific relationship to these
quotient containers, we have begun investigating their application to programming in the
Theory of Species which was Joyal’s motivation for developing analytic functors.

Bibliography
[1] Michael Abbott. Categories of Containers. PhD thesis, University of Leicester,
2003.
[2] Michael Abbott, Thorsten Altenkirch, and Neil Ghani. Categories of containers. In
Andrew Gordon, editor, Proceedings of FOSSACS 2003, number 2620 in Lecture
Notes in Computer Science, pages 23–38. Springer-Verlag, 2003.
[3] Michael Abbott, Thorsten Altenkirch, Neil Ghani, and Conor McBride. Derivatives
of containers. In Martin Hofmann, editor, Typed Lambda Calculi and Applications,
TLCA 2003, number 2701 in Lecture notes in Computer Science, pages 16–30.
Springer, 2003.
[4] Thorsten Altenkirch and Conor McBride. Generic programming within
dependently typed programming. In Generic Programming, 2003. Proceedings
of the IFIP TC2 Working Conference on Generic Programming, Schloss Dagstuhl,
July 2002.
[5] E. S. Bainbridge, Peter J. Freyd, A. Scedrov, and P. J. Scott. Functorial
polymorphism, preliminary report. In Gerard Huet, editor, Logical Foundations
of Functional Programming, chapter 14, pages 315–327. Addison-Wesley, 1990.
[6] Marcelo Fiore, Gordon Plotkin, and Daniele Turi. Abstract syntax and variable
binding (extended abstract). In Proc. 14th LICS Conf., pages 193–202. IEEE,
Computer Society Press, 1999.
[7] Martin Hofmann. On the interpretation of type theory in locally cartesian closed
categories. In CSL, pages 427–441, 1994.
[8] Bart Jacobs. Categorical Logic and Type Theory. Number 141. Elsevier, 1999.
[9] C. Barry Jay. A semantics for shape. Science of Computer Programming, 25:251–
283, 1995.
[10] C. Barry Jay and J. R. B. Cockett. Shapely types and shape polymorphism.
In D. Sannella, editor, Programming Languages and Systems - ESOP ’94: 5th
European Symposium on Programming, U.K., April 1994, Proceedings, Lecture
Notes in Computer Science, pages 302–316. Springer-Verlag, 1994.
[11] André Joyal. Foncteurs analytiques et espéces de structures. In Combinatoire
énumérative, number 1234 in LNM, pages 126 – 159. 1986.
[12] Saunders Mac Lane. Categories for the Working Mathematician. Number 5 in
Graduate Texts in Mathematics. Springer-Verlag, 1971.
[13] M.P.Fiore and T.Leinster. Objects of categories as complex numbers. Advances in
Mathematics., 2004. To appear.

You might also like