<<

Monads and Eects

Nick Benton John Hughes and Eugenio Moggi

Microsoft Research

Chalmers Univ

DISI Univ di Genova Genova Italy

moggidisiunigeit

Abstract A tension in language design has b een b etween simple se

mantics on the one hand and rich p ossibilities for sideeects exception

handling and so on on the other The intro duction of monads has made

a large step towards reconciling these alternatives First prop osed by

Moggi as a way of structuring semantic descriptions they were adopted

by Wadler to structure Haskell programs and now oer a general tech

nique for delimiting the scop e of eects thus reconciling referential trans

parency and imp erative op erations within one programming language

Monads have b een used to solve longstanding problems such as adding

p ointers and assignment interlanguage working and exception handling

to Haskell without compromising its purely functional The

course will intro duce monads eects and related notions and exemplify

their applications in programming Haskell and in compilation MLj

The course will present typ ed metalanguages for monads and related

categorical notions and describ e how they can b e further rened by in

tro ducing eects

Research partially supp orted by MURST and ESPRIT WG APPSEM

Monads and Computational Typ es

Monads sometimes called triples have b een considered in Category Theory

CT relatively late only in the late fties Monads and comonads the dual

of monads are closely related to adjunctions probably the most p ervasive no

tion in CT The connection b etween monads and adjunctions was established

indep endently by Kleisli and Eilenb ergMo ore in the sixties Monads like ad

junctions arise in many contexts eg in algebraic theories Go o d CT

for monads are ManBWBor It is not surprising that monads arise also

in applications of CT to Science CS We will use monads for giving

denotational semantics to programming languages and more sp ecically as a

way of mo deling computational types Mog

to interpret a programming language in a category C we distinguish

the ob ject A of values of typ e A from the ob ject TA of computations

of typ e A and take as of programs of typ e A the elements

of TA In particular we identify the typ e A with the ob ject of values of

typ e A and obtain the ob ject of computations of typ e A by applying an

unary typ econstructor T to A We call T a notion of computation since

it abstracts away from the typ e of values computations may pro duce

Example We give few notions of computation in the category of sets

partiality TA A ie A fg where is the diverging computation

nondeterminism TA P A ie the of nite of A

f in

S

L

sideeects TA AS where S is a set of states eg a set U of stores

or a set of inputoutput sequences U

exceptions TA A E where E is the set of exceptions

A

R

TA R where R is the set of results

U

interactive input TA X A X where U is the set of characters

More explicitly TA is the set of U branching trees with only nite paths and

Alab elled leaves

interactive output TA X A U X ie U A up to iso

Further examples in the category of cp os could b e given based on the denota

tional semantics for various programming languages

Remark Many of the examples ab ove are instances of the following one given

a single sorted algebraic theory T h let TA jT Aj ie the carrier of the

T h

free T halgebra T A over A One could consider combinations of the examples

T h

ab ove eg

S S

TA A E S and TA AS E capture imp erative programs

with exceptions

TA X P A ActX captures parallel programs interacting via a

f in

set Act of actions in fact TA is the set of nite synchronization trees up to

strong bisimulation

S

TA X P A X S captures parallel imp erative programs with

f in

shared memory

Wad advo cates a similar idea to mimic impure programs in a pure functional

language Indeed the Haskell community has gone a long way in exploiting this

approach to reconcile the advantages of pure functional programming with the

exibility of imp erative or other styles of programming The analogies of com

putational typ es with eect systems GL have b een observed by Wad but

formal relations b etween the two have b een established only recently eg see

Wad

In the denotational semantics of programming languages there are other in

formal notions mo deled using monads for instance col lection types in database

languages BNTW or col lection classes in ob jectoriented languages Man

It is imp ortant to distinguish the mathematical notion of monad or its rene

ments from informal notions such as computational and collection typ es which

are dened by examples In fact these informal notions can b e mo deled with a

b etter degree of approximation by considering monads with additional prop er

ties or additional structures When considering these renements it is often the

case that what seems a natural requirement for mo deling computational typ es

is not appropriate for mo deling collection typ es for instance

It seems natural that programming languages can express divergent compu

tations and more generally they should supp ort recursive denitions of pro

grams therefore computational typ es should come equipp ed with a constant

TA for the divergent computation and a least xp oint combinator

Y TA TA TA

While it seems natural that a collection should have only a nite numb er

of elements and there should b e an empty collection TA and a way of

merging two collections using a binary op eration TA TA TA

There are several equivalent denitions of monad the same happ ens with

adjunctions Man gives three denitions of monadtriple called in monoid

form the one usually adopted in CT b o oks in form the most in

tuitive one for us and in clone form which takes comp osition in the Kleisli

category as basic We consider only triples in monoid and extension form

Notation We assume know ledge of basic notions from category theory such

as category functor and natural transformation In some cases familiarity with

universal constructions products sums exponentials and adjunction is as

sumed We use the fol lowing notation

given a category C we write

jC j for the set of its objects

C A B for the homset of morphisms from A to B

g f and f g for the composition A B C f g

id for the identity on A

A

F C D means that F is a functor from C to D and

F G means that is a natural transformation from F to G

G

D means that G is right adjoint to F F is left adjoint to G C

F

Denition Kleisli tripletriple in extension form A Kleisli triple

over a category C is a triple T where T jC j jC j A TA for

A

A jC j f TA TB for f A TB and the fol lowing equations hold

id

TA

A

f f for f A TB

A

f g f g for f A TB and g B TC

Kleisli triples have an intuitive justication in terms of computational typ es

is the inclusion of values into computations

A

A

a A a TA

f is the extension of a f from values to computations to a function

from computations to computations which rst evaluates a computation and

then applies f to the resulting value

f

a A f a TB



f

c TA let ac in f a TB

In order to justify the for a Kleisli triple we have rst to intro duce a

category C whose morphisms corresp ond to programs We pro ceed by analogy

T

with the categorical semantics for terms where typ es are interpreted by ob jects

and terms of typ e B with a parameter free variable of typ e A are interpreted

by morphisms from A to B Since the of programs of typ e B are

supp osed to b e elements of TB programs of typ e B with a parameter of typ e A

ought to b e interpreted by morphisms with co domain TB but for their domain

there are two alternatives either A or TA dep ending on whether parameters of

typ e A are identied with values or computations of typ e A We cho ose the rst

alternative b ecause it entails the second Indeed computations of typ e A are the

same as values of typ e TA So we take C A B to b e C A T B It remains to

T

dene comp osition and identities in C and show that they satisfy the unit and

T

asso ciativity axioms for categories

over C the Denition Kleisli category Given a Kleisli triple T

Kleisli category C is dened as fol lows

T

the objects of C are those of C

T

the set C A B of morphisms from A to B in C is C A T B

T T

the identity on A in C is A TA

T A

f C A B fol lowed by g C B C in C is f g A TC

T T T

It is natural to take as the identity on A in the category C since it maps a

A T

parameter x to x ie to x viewed as a computation Similarly comp osition in

C has a simple explanation in terms of the intuitive meaning of f in fact

T

f g

x A f x TB y B g y TC



f g

x A let y f x in g y TC

ie f followed by g in C with parameter x is the program which rst evaluates

T

the program f x and then feed the resulting value as parameter to g At this

p oint we can give also a simple justication for the three axioms of Kleisli triples

namely they are equivalent to the following unit and asso ciativity axioms which

say that C is a category

T

f for f A TB f

B

f f for f A TB

A

f g h f g h for f A TB g B TC and h C TD

Example We go through the examples of computational typ es given in Ex

ample and show that they are indeed part of suitable Kleisli triples

partiality TA A A fg

is the inclusion of A into A

A

if f A TB then f and f a f a when a A

nondeterminism TA P A

f in

is the singleton a fag

A

if f A TB and c TA then f c ff xjx cg

S

sideeects TA AS

is the map a s Sa s

A

if f A TB and c TA then f c s Slet a s c s in f a s

exceptions TA A E

is the injection map a inl a

A

if f A TB then f inr e inr e where e E and f inl a f a

where a A

A

R

continuations TA R

A

is the map a k R k a

A

B

if f A TB and c TA then f c k R ca Af a k

U

interactive input TA X A X

maps a to the tree consisting only of one leaf lab elled with a

A

if f A TB and c TA then f c is the tree obtained by replacing leaves

of c lab elled by a with the tree f a

interactive output TA X A U X

is the map a a

A

if f A TB then f s a s s b where f a s b and s s is

the concatenation of s followed by s

Exercise Dene Kleisli triples in the category of cp os similar to those given

in Example but ensure that each computational typ e TA has a least

DIFFICULT in cp os there are three Kleisli triple for nondeterminism one

for each p owerdomain construction

Exercise When mo deling a programming language the rst choice to make

is which category to use For instance it is imp ossible to nd a monad over

the category of sets which supp ort recursive denitions of programs one should

work in the category of cp os or similar categories Moreover there are other

asp ects of programming languages that are orthogonal to computational typ es

eg recursive and p olymorphic typ es that cannot b e mo dels in the category of

sets one has to work in categories like that of cp os or in realizability models

If one wants to mo del a twolevel language where there is a notion of static

and dynamic then the following categories are particularly appropriate

the category sC where C can b e any CCC is dened as follows

an ob ject is a pair A A with A A jC j A is the static and A is the

s d s d s d

dynamic part

a morphism in sC A A B B is a pair f f with f C A B

s d s d s d s s s

and f C A A B thus the static part of the result dep ends only on

d s d d

the static part of the input

the category F amC where C can b e any CCC with small limits is dened

as follows

an ob ject is a family A ji I with I a set and A jC j for every i I

i i

a morphism in F amC A ji I B jj J is a pair f g with f I J

i j

and g is an I index family of morphisms st g C A B for every i I

i i f i

Dene Kleisli triples in the categories sC and F amC similar to those given

in Example assume that C is the category of sets Notice that in a twolevel

language static and dynamic computations dont have to b e the same

Monads and Related Notions

This section contains denitions and facts that are not essential to the sub

sequent developments First we establish the equivalence of Kleisli triples and

monads

Denition Monadtriple in monoid form A monad over C is a triple

T are natural T and T T where T C C is a functor id

C

transformations and the fol lowing diagrams commute

T

TA TA A

TA T A TA T A T A

T

A A A

id id

TA TA

R

TA TA T A

A

Prop osition There is a bijection between Kleisli triples and monads

Proof Given a Kleisli triple T the corresp onding monad is T

where T is the extension of the function T to an endofunctor by taking T f

f for f A B and id Conversely given a monad T the

B A

TA

corresp onding Kleisli triple is T where T is the restriction of the functor

T to ob jects and f T f for f A TB

B

Denition Eilenb ergMo ore category Given a monad T over

T

C the Eilenb ergMo ore category C is dened as fol lows

T

the objects of C are T algebras ie morphisms TA A in C st

A A

TA A TA T A

T

id

A

R

A A TA

A is cal led the carrier of the T algebra

T

a morphism f C from TA A to TB B is a morphism

f A B in C st

T f

TB TA

B TA

f

T

identity and composition in C are like in C

G

Any adjunction C D induces a monad over C with T F G The

F

Kleisli and Eilenb ergMo ore categories can b e used to prove the ie that

any monad over C is induced by an adjunction Moreover the Kleisli category can

T

consisting of the free T algebras b e identied with the full subcategory of C

Prop osition Given a monad T over C there are two adjunctions

U U

T

C C C C

T

F F

T

which induce T Moreover there is a ful l and faithful functor C C st

T

F

T

C C

F

R

C

T

Proof The action of functors on ob jects are as follows U TA A A

FA T A TA U A TA F A A and A T A TA

A A

Denition Monad morphism Given T and T monads

over C a monadmorphism from the rst to the second is a natural transfor

mation T T st

A A

TA T A A

A TA

A

R

T A T TA

I

T

A

A

T A

An equivalent denition of monad morphism in terms of Kleisli triples is a

family of morphisms TA T A for A jC j st

A

A A

A

0

f f for f A TB

B A B

We write M onC for the category of monads over C and monad morphisms

There is also a more general notion of monad morphism which do es not require

that the monads are over the same category Monad morphisms allow to view

T algebras as T algebras with the same underlying carrier more precisely

Prop osition There is a bijective correspondence between monad morphisms

0 V

T T

C C

0

T T

T T and functors V C C st U

U

R

C

Proof The action of V on ob jects is V T A A TA A and

A

T V

A A

TA is dened in terms of V as T T A T A

A A

Remark Fil uses a layering T T A T A of T over T in place of a

A

monad morphism TA T A The two notions are equivalent in particular

A

0

is given by V ie

A T A

A A

Metalanguages with Computational Typ es

It is quite inconvenient to work directly in a sp ecic category or with a sp ecic

monad Mathematical provides a simple solution to abstract away from

sp ecic mo dels x a language dene what is an of the language

in a mo del nd a on the language that capture the desired

prop erties of mo dels When the formal system is sound one can forget ab out

the mo dels and use the formal system instead Moreover if the formal system

is also complete then nothing is lost as far as one is concerned with prop erties

expressible in the language and valid in all mo dels Several formal systems have

b een proved sound and complete wrt certain class of categories

many sorted equational logic corresp onds to categories with nite pro ducts

simply typ ed calculus corresp onds to cartesian closed categories CCC

intuitionistic higherorder logic corresp onds to elementary top oses

Remark To ensure soundness wrt the given classes of mo dels the ab ove

formal systems should cop e with the p ossibility of empty carriers While in

it is often assume that all carriers are inhabited Categorical

Logic is the branch of CT devoted mainly at establishing links b etween formal

systems and classes of categorical structures

Rather than giving a complete formal system we say how to add computational

typ es to your favorite formal system for instance higherorder calculus or a

calculus with dep endent typ es like a logical framework The only assumption

we make is that the formal system should include many sorted equational logic

this rules out systems like the linear calculus More sp ecically we assume

that the formal system has the following judgments

ie is a wellformed context

ty pe ie is a wellformed typ e in context

e ie e is a wellformed of typ e in context

pr op ie is a wellformed prop osition in context

ie the wellformed prop osition in context is true

and that the following rules are part of the formal system or derivable

ty pe

x DV x

x x

e e

this says when an equation is wellformed

e e pr op

e x

weak x DV sub

x x e

e e e e e e e

e e e e e e

x pr op e e x e

cong

x e

Remark More complex formal systems may require other forms of judgment

eg equality of typ es and contexts or other sorts b esides ty pe along the line

of Pure Typ e Systems The categorical interpretation of typ ed calculi including

those with dep endent typ es is describ ed in PitbJac

The rules for adding computational typ es are

e ty pe

lift T

T ty pe e T

T

e T x e T

x FV let

let x e in e T

T

e is the programcomputation that simply returns the value e while

T

let xe in e is the computation which rst evaluates e and binds the

T

result to x then evaluates e

In calculi without dep endent typ es the sidecondition x FV in the let

rule is automatically satised From now on we ignore such sideconditions

e T x e e T

let

let xe in e let xe in e T

T T

this rule expresses congruence for the letbinder

e T x e T x e T

asso c

let x let x e in e in e

T T

let x e in let x e in e T

T T

this rule says that only the order of evaluation matters not the parentheses

e x e T

T

let xe in e e x e T

T T

e T

T

let xe in x e T

T T

these rules say how to eliminate trivial computations ie of the form e

T

Remark Mog describ es the interpretation of computational typ es in a

simply typ ed calculus and establishes soundness and results while

Mog extends such results to logical systems including evaluation modalities

prop osed by Pitts

For interpreting computational typ es monads are not enough one has to use

parameterized monads The parameterization is directly related to the form of

typ edep endency allowed by the typ ed calculus under consideration The need to

consider parametrized forms of categorical notions is by now a wellundersto o d

fact in categorical logic it is not a p eculiarity of computational typ es

We sketch the categorical interpretation in a category C with nite pro ducts of

a simply typ ed metalanguage with computational typ es see Mog for more

details The general pattern for interpreting a simply typ ed calculus according

to Lawveres functorial semantics go es as follows

a context and a typ e ty pe are interpreted by ob jects of C by abuse

of notation we indicate these ob jects with and resp ectively

a term e is interpreted by a morphism f in C

a well formed equational e e is true i f f as

morphisms in C

Figure gives the relevant clauses of the interpretation Notice that for in

terpreting let one needs a parameterized extension op eration which maps

f C A TB to f C TA TB

RULE SEMANTICS

T

ty pe

T ty pe T

lift

e f

e T f T

T

let

e T f T

x e T f T

T let xe in e T id f f

T

Fig simple interpretation of computational typ es

Syntactic Sugar and Alternative Presentations

One can dene convenient derived notation for instance

an iteratedlet let x e in e which is dened by induction on jej jx j

T

xe e in e let x e in let xe in e let in e e let x

T T T T

Haskells donotation inspired by monad comprehension see Wad ex

tends the iteratedlet by allowing pattern matching and lo cal denitions

In higherorder calculus the typ e and termconstructors can b e replaced

by constants

T b ecomes a constant of kind where is the kind of all typ es

e and let xe in e are replaced by p olymorphic constants

T T

unit X X TX l et X Y X TY TX TY

T T

X x X x and where unit

T T

l et X Y f X T Y c T X let x c in f x

T T

In this way the rule let follows from the rule for abstraction and the other

three equational rules can b e replaced with three equational axioms without

premises eg T can b e replaced by

X Y x X f X TY let x x in f x f x TY

T T

The p olymorphic constant unit corresp onds to the natural transformation

T

In higherorder calculus one can dene also p olymorphic constants

map X Y X Y TX TY f l at X T X TX

T T

corresp onding to the action of the functor T on morphisms and to the natural

transformation

X Y f X Y c T X let xc in f x map

T T T

X c T X let xc in x f l at

T T

The axiomatization taking as primitive the p olymorphic constants unit and

T

l et amounts to the denition of triple in extension form one can envisage an

T

alternative axiomatization corresp onding to that of triple in monoid form which

takes as primitive the p olymorphic constants map unit and f l at

T T T

Categorical Denitions in the Metalanguage

The main p oint for intro ducing a metalanguage is to provide an alternative to

working directly with mo delscategories In particular one exp ect that categor

ical notions related to monads such as algebra and monad morphisms can b e

reformulated axiomatically in a metalanguage with computational typ es

Denition Eilenb ergMo ore algebras TA A is a T algebra i

x A x x A

T

c T A let xc in x let xc in x A

T T T

f A B is a T algebra morphism from TA A to TB B i

c TA f c let xc in f x B

T T

We can consider metalanguages with many computational typ es corresp ond

ing to dierent monads on the same category In particular to dene monad

morphisms we use a metalanguage with two computational typ es T and T

Denition Monad morphism A constant X T X T X is a

monad morphism from T to T i

0

T X X x X X x x

T T

X Y c T X f X TY Y let x c in f x

T

0

x X c in Y f x T Y let

T

Metalanguages for Denotational Semantics

Translation of a language into another provides a simple and general way to give

semantics to the rst language in terms of a semantics for the second In deno

tational semantics it is quite common to dene the semantics of a programming

language PL by translating it into a typ ed metalanguage ML The idea is as

old as denotational semantics see Sco so the main issue is whether it can

b e made into a viable technique capable of dealing with complex programming

languages Before b eing more sp ecic ab out what metalanguages to use let us

discuss what are the main advantages of semantics via translation

to reuse the same ML for translating several programming languages

PL

H

H

tr ansl

H

H

Hj

inter p

ML C

tr ansl

PL

n

Here we are implicitly assuming that dening a translation from PL to ML

is simpler than directly dening an interpretation of PL

In this case it is worth putting some eort in the study of ML In fact once

certain prop erties of ML have b een established eg reasoning principles or

computational adequacy it is usually easy to transfer them to PL via the

translation

to cho ose ML according to certain criteria usually not met by programming

languages eg

a metalanguage built around few orthogonal concepts is simpler to study

on the contrary programming languages often intro duce syntactic sugar

for the b enet of programmers

ML may b e equipp ed with a logic so that it can b e used for formalizing

reasoning principles or for translating sp ecication languages

ML may b e chosen as the internal language for a class of categories eg

CCC or for a sp ecic semantic category eg that of sets or cp os

to use ML for hiding details of semantic categories see Gor For in

stance when ML is the internal language for a class of categories it has one

intended interpretation in each of them therefore a translation into ML will

induce a variety of interpretations

C

inter p

tr ansl

PL ML

H

H

H

H

jH

inter p

C

n

even when ML has only one intended interpretation it may b e dicult to

work with the semantic category directly

A go o d starting p oint for a metalanguage is to build it on top of a fairly

standard typ ed calculus more controversial issues are

whether the metalanguage should b e equipp ed with some logic ranging from

equational logic to higherorder predicate logic

whether the metalanguage should b e itself a programming language ie to

have an op erational semantics

We will discuss how the metalanguages with computational typ es can help

in structuring the translation from PL to ML by the intro duction of auxiliary

notation see MosMog

tr ansl tr ansl

ML ML PL

and by incrementally dening auxiliary notation as advo cated in Fil

LHJLH and CMMog

tr ansl tr ansl tr ansl tr ansl

PL ML ML ML

n

Remark The solutions prop osed are closely related to general techniques

in algebraic specications such as abstract datatyp e stepwise renement and

hierarchical sp ecications

Computational Typ es and Structuring

A typical problem of denotational and op erational semantics is the following

when a programming language is extended its semantics may need to b e exten

sively redened For instance when extending a pure functional language with

sideeects or exceptions we have to redene the op erationaldenotational se

mantics every time we considered a dierent extension The problem remains

even when the semantics is given via translation in a typ ed lamb dacalculus

one would keep redening the translation In Mos this problem is identied

very clearly and it is stressed how the use of auxiliary notation may help in

making semantic denitions more reusable

Mog identies monads as an imp ortant structuring device for denotational

semantics but not for op erational semantics The basic idea is that there

is a unary typ e constructor T called a notion of computation and terms

of typ e T should b e thought as programs which computes values of typ e

The interpretation of T is not xed it varies according to the computational

features of the programming language under consideration Nevertheless one

can identies some op erations for sp ecifying the order of evaluation and basic

prop erties of them which should b e common to all notions of computation This

suggests to translate a programming language PL into a metalanguage ML

T

with computational typ es where the signature gives additional op erations

and their prop erties In summary the monadic approach to denotational

semantics consists of three steps ie given a programming language PL

identify a suitable metalanguage ML this hides the interpretation of

T

T and like an interface hides the implementation of an abstract datatyp e

dene a translation of PL into ML

T

construct a mo del of ML eg via translation into a metalanguage ML

T

without computational typ es

By a suitable choice of one can nd a simple translation from PL to ML

T

which usually do es not have to b e redened only extended when PL is ex

tended At the same time one can keep the translation of ML into ML

T

fairly manageable

To exemplify the use of computational typ es we consider several program

ming languages viewed as calculi with constants and for each of them we

dene translations into a metalanguage ML with computational typ es for

T

a suitable choice of and indicate a p ossible interpretation for computational

typ es and

CBN Translation Haskell We consider a simple fragment of Haskell corre

sp onding to the following typ ed calculus we ignore issues of typ e

thus terms have explicit typ e information

T y pe Int typ e of integers

H ask ell

functional typ e

pro duct typ e

e E xp x variable

H ask ell

n j e e numerals and integer addition

if e then e else e conditional

let x e in e lo cal denition

x e recursive denition

x e abstraction

e e application

e e pairing

e pro jection

i

The typ e system for Haskell derives judgments of the form e saying

n

T y pe T y pe

H ask ell

Int Int

n n

T T

n n

T T

n

e E xp e E xp

H ask ell

x x

n n

T

n n

e e let x x e e in x x

T T

n n n

if e then e else e let xe in if x then e else e

T

n n n

let x e in e x T e e

n n n

x e Y x T e

n n

x e x T e

T

n n

e e let f e in f e

T

n n

e e e e

T

n

e let xe in x

i T i

Fig CBN translation of Haskell

that a term e has typ e in the typing context In denotational semantics

one is interested in interpreting only wellformed terms since programs rejected

by a typ echecker are not allowed to run thus we want to dene a translation

mapping wellformed terms e of the programming language into well

PL

formed terms e of the metalanguage with computational typ es

ML

n

by induction on typ es and raw terms More precisely we dene a translation

e called the CBN translation see Figure When fx ji mg e

i i PL

n n

is a wellformed term of Haskell one can show that fx T ji mg e

i ML

i

n

T is a wellformed term of the metalanguage with computational typ es The

signature for dening the CBN translation of Haskell consists of

Y X TX TX TX a least xp oint combinator

a signature for the datatyp e of integers

Remark The key feature of the CBN translation is that variables in the

programming languages are translated into variables ranging over computational

typ es Another imp ortant feature is the translation of typ es which basically

guides in combination with op erational considerations the translation of terms

Exercise Extend Haskell with p olymorphism as in ndorder calculus ie

T y pe X j j X e E xp j X e j e

H ask ell H ask ell

There is a problem to extend the CBN translation to p olymorphic typ es To

overcome the problem assume that computational typ es commutes with p oly

morphism ie the following map is an iso

c T X X let xc in x X X T

T T

In realizability mo dels several monads eg lifting satisfy this prop erty indeed

the isomorphism is often an identity

Algol Translation Some CBN languages including Algol and PCF allow

computational eects only at base typ es Computational typ es play a limited

role in structuring the denotational semantics of these languages nevertheless it

is worth to compare the translation of such languages with that of Haskell We

consider an idealizedAlgol with a xed set of lo cations Syntactically it is an

extension of simple Haskell with three base typ es Lo c for integer lo cations Int

for integer expressions and Cmd for commands In Algollike languages a lo cation

is often identied with a pair consisting of an expression and an acceptor ie

Lo c Int Int Cmd

T y pe Lo c j Int j Cmd j j

Alg ol

e E xp x j l lo cation

Alg ol

j n j e e j e contents of a lo cation

if e then e else e

skip j e e null and assignment commands

e e sequential comp osition of commands

let x e in e j x e j x e j e e j e e j e

i

a

see Figure is dened by induction on typ es The Algol translation

and raw terms e When fx ji mg e is a wellformed term of Algol

i i PL

a a a

one can show that fx ji mg e is a wellformed term of the

i ML

i

metalanguage with computational typ es

Remark The Algol translation seems to violate a key principle namely that

the translation of a program should have computational typ e But in Algol valid

programs are exp ected to b e terms of base typ e and the Algol translation in

deed maps base typ es to computational typ es More generally one should observe

that the Algol translation maps Algol typ es in carriers of T algebras Indeed

T algebras for a strong monads are closed under arbitrary pro ducts and ex

p onentials more precisely A A is the carrier of a T algebra whenever A and

A

A are and B is the carrier of a T algebra whenever B is EXERCISE prove

these facts in the metalanguage The T algebra structure on the translation of

typ es is used for dening the translation of terms namely to extend the let and

xp oint combinator from computational typ es to T algebras

e T x e U T

let

let xe in e U T let xe in e

T T T

a

T y pe T y pe

Alg ol

Lo c T Lo c

Int T Int

Cmd T

a a

a a

a

e E xp e E xp

Alg ol

x x

n n

T

a a

e e let x x e e in x x

T T

a a a

if e then e else e let xe in if x then e else e

T

a a a

let x e in e x e e

a a a

x e Y x e

a a

x e x e

a a

e e e e

a a

e e e e

a

e e

i i

l l

T

a

e let l e in g et l

T

skip

T

a a

e e let l ne e in set l n

T

a a

e e let e in e

T

Fig Algol translation

x e U T

Y

Y x e Y c T ex c U T

T

The Algol translation suggests to put more emphasis on T algebras Indeed

Lev has prop osed a metalanguage for monads with two classes of typ es

value typ es interpreted by ob jects in C and computation typ es interpreted by

T

ob jects in C

The signature for dening the Algol translation consists of

Y X TX TX TX like for the Haskell translation

a signature for the datatyp e of integers like for the Haskell translation

a typ e Lo c of lo cations with a xed set of constants l Lo c and op erations

g et Lo c T Int and set Lo c Int T to getstore an integer frominto

a lo cation

Remark In Algol expressions and commands have dierent computational

eects namely expressions can only read the state while commands can also

S

mo dify the state Therefore one would have to consider two monads T A A

sr

S

for state reading computations and T A AS for computations with side

se

eects and a monad morphism from T to T

sr se

CBV Translation SML We consider a simple fragment of SML with integer

lo cations Syntactically the language is a minor variation of idealized Algol

more precisely Cmd is replaced by Unit and skip by sequential comp osition

of commands has b een removed b ecause denable recursive denitions are

restricted to functional typ es

T y pe Lo c j Int j Unit j j

SML

e E xp x j l j n j e e j e j if e then e else e j j e e j

SML

let x e in e j f x e j

x e j e e j e e j e

i

v

see Figure is dened by induction on typ es The CBV translation

and raw terms e When fx ji mg e is a wellformed term of SML

i i PL

v v v

one can show that fx ji mg e T is a wellformed term of the

i ML

i

metalanguage with computational typ es The signature for dening the CBV

translation is the same used for dening the Algol translation

Exercise So far we have not said how to interpret the metalanguages used as

target for the various translations Prop ose interpretations of the metalanguages

in the category of cp os rst cho ose a monad for interpreting computational

typ es then explain how the other symb ols in the signature should b e inter

preted

Exercise The translations considered so far allow to validate equational laws

for the programming languages by deriving the translation of the equational

v

T y pe T y pe

SML

Lo c Lo c

Int Int

Unit

v v

T

v v

v

e E xp e E xp

SML

x x

T

n n

T

v v

e e let x x e e in x x

T T

v v v

if e then e else e let xe in if x then e else e

T

v v

let x e in e let xe in e

T

v v v v

f x e Y f x e

v v

x e x e

T

v v

e e let f xe e in f x

T

v v

e e let x x e e in x x

T T

v

e let xe in x

i T i T

l l

T

v

e let l e in g et l

T

T

v v

in set l n e e e let l ne

T

Fig CBV translation of SML

laws in the metalanguage Say whether and for functional typ es ie x

e e e x e and x e x e with x FV e are

valid in Haskell Algol or SML If they are not valid suggest weaker equational

laws that can b e validate This exercise indicates that one should b e careful to

transfer reasoning principle for the calculus to functional languages

Exercise Consider Haskell with integer lo cations and extend the CBN trans

lation accordingly Which signature should b e used

Exercise In SML one can create new lo cations using the construct ref e

Consider this extension of SML and extend the CBV translation accordingly

Which signature and monad T in the category of cp os should b e used

Exercise Consider SML with lo cations of any typ e and extend the CBV

translation accordingly Which signature should b e used you may nd con

venient to assume that the metalanguage includes higherorder calculus It

is very dicult to nd monads able to interpret such a metalanguage

Incremental Approach and Monad Transformers

The monadic approach to denotational semantics has a caveat When the pro

gramming language PL is complex the signature identied by the monadic

approach can get fairly large and the translation of ML into ML may

T

b ecome quite complicated

One can alleviate the problem by adopting an incremental approach in

dening the translation of ML into ML The basic idea is to adapt to this

T

setting the techniques and mo dularization facilities advo cated for formal soft

ware development in particular the desired translation of ML into ML

T

corresp onds to the implementation of an abstract datatyp e in some given lan

guage In an incremental approach the desired implementation is obtained by

a sequence of steps where each step constructs an implementation for a more

complex datatyp e from an implementation for a simpler datatyp e

Haskell constructor classes and to a less extend SML mo dules provide

a very convenient setting for the incremental approach see LHJ the

typ e inference mechanism allows concise and readable denitions while

typ echecking detects most errors What is missing is only the ability to

express and validate equational prop erties which would require extra

features typical of Logical Frameworks see Mog

To make the approach viable we need a collection of selfcontained parameter

ized polymorphic mo dules with the following features

they should b e p olymorphic ie for any signature or at least for a wide

range of signatures the mo dule should take an implementation of and

construct an implementation of where is xed

new new

they could b e parametric ie the construction and the signature may

new

dep end on parameters of some xed signature

par

The p olymorphic requirement can b e easily satised when one can implement

without changing the implementation of this is often the case in soft

new

ware development However the constructions we are interested in are not per

sistent since they involve a reimplementation of computational typ es and con

sequently of The translations we need to consider are of the form

I ML ML

T par new T par

where are the new symb ols dened by I the old symb ols redened by

new

I and the parameters of the construction which are unaected by I In

par

general I can b e decomp osed in

a translation I ML ML dening the new

new T par new T par

symb ols in and redening computational typ es

new

translations I ML ML redening an old symb ol

op T op T par op

op in isolation consistently with the redenition of computational typ es

for each p ossible typ e of symb ol one may have in

Recently Fil has prop osed a more exible approach which uses meta

languages with several monads T rather than only one and at each step it i

intro duces a new monad T and new op erations dened in term of the pre

existing ones without changing the meaning of the old symb ols Therefore one

is considering denitional extensions ie translations of the form

0

ML I ML

old old T T T

i2n i2n

new

In Filinskis approach one can use which are the identity on ML

old T

i2n

the translations I and I whenever p ossible and more ad ho c denitions

new op

otherwise In fact when Filinski intro duces a new monad T he intro duces also

two op erations called monadic reection and reication

reect X T X reify X T X

that establish a bijection b etween T X and its implementation ie a typ e in

the preexisting language Therefore one can dene op erations related to T by

moving back and forth b etween T and its implementation as done in the case

of op erations dened on an abstract datatyp e

Semantically a monad transformer is a function F jM onC j jM onC j

mapping monads over a category C to monads We are interested in monad

transformers for adding computational eects therefore we require that for any

monad T there should b e a monad morphism in T FT It is often the case

T

that F is a functor on M onC and in b ecomes a natural transformation from

id to F Syntactically a monad transformer is a translation

M onC

0

I ML ML

F T T par T par

which is the identity on ML In other words we express the new monad

T par

T in terms of the old monad T and the parameters sp ecied in In the

par

sequel we describ e in a higherorder calculus several monad transformers

corresp onding to the addition of a new computational eect more precisely we

dene

the new monad T and the monad morphism in T T

the op erations on T computations asso ciated to the new computational ef

fect

an op eration op X A B T X T X extending to T

computations a preexisting op eration op X A B TX TX

on T computations

Monad Transformer I for Adding SideEects

se

signature for parameters

par

states S

signature for new op erations

new

lo okup l k p T S

up date upd S T

denition of new monad T and monad morphism in T T

T X S T X S

0

sx s x

T T

0

xc in f x slet x s c s in f x s let

T T

in X c slet x c in x s

T T

denition of new op erations

l k p ss s

T

upd s s s

T

extension of old op eration

op X a f sop X S a bf b s

Remark The op erations l k p and upd do not t the format for op However

given an op eration op A TB one can dene an op eration op X A

B TX TX in the right format by taking op X a f let b op a in f b

T

Monad Transformer I for Adding Exceptions

ex

signature for parameters

par

exceptions E

signature for new op erations

new

raise r aise X E T X

handle handl e X E T X T X T X

denition of new monad T and monad morphism in T T

T X T X E

0

inl x x

T T

0

xc in f x let uc in case u of x f x j n inr n let

T T T

in X c let xc in inl x

T T

denition of new op erations

r aise X n inr n

T

handl e X f c let uc in case u of x inl x j n f n

T T

extension of old op eration

op X a f op X E a f

Remark In this case the denition of op is particularly simple and one

can show that the same denition works for extending a more general typ e of

op erations

Monad Transformer I for Adding Complexity

co

signature for parameters

par

monoid M

M

M M M we use inx notation for

to prove that T is a monad we should add axioms saying that M is

a monoid

signature for new op erations

new

cost tick M T

denition of new monad T and monad morphism in T T

T X T X M

0

x x

T T

0

xc in f x let x m c in let y nf x in y m n let

T T T T

in X c let xc in x

T T

denition of new op erations

tick m m

T

extension of old op eration

op X a f op X M a f

Monad Transformer I for Adding Continuations

con

signature for parameters

par

results R

signature for new op erations

new

ab ort abor t X R T X

callcc cal l cc X Y X T Y T X T X

denition of new monad T and monad morphism in T T

T X X TR TR

0

k k x x

T

0

xc in f x k c xf x k let

T

in X c k let x c in k x

T

denition of new op erations

abor t X r k r

T

cal l cc X Y f k f xk k x k

T

extension of old op eration

op X a f k op R a bf b k

Remark The op eration cal l cc do es not t the sp ecied format for an old

op eration and there is no way to massage it into such format Unlike the others

monad transformers I do es not extend to a functor on M onC

con

Exercise For each of the monad transformer prove that T is a monad

Assume that T is a monad and use the equational axioms for higherorder

calculus with sums and pro ducts including axioms

Exercise For each of the monad transformer dene a xp oint combinator

for the new computational typ es Y X T X T X T X given a

xp oint combinator for the old computational typ es Y X TX TX

TX In some cases one should use the derived xp oint combinator Y for carriers

of T algebras

Exercise Dene a monad transformer I for statereaders ie T X S

sr

TX What could b e Dene a monad morphism from T to T

new sr se

Exercise Check which monad transformers commutes up to isomorphism

For instance I and I do not commute more precisely one gets

se ex

T X S T X E S when adding rst sideeects and then

seex

exceptions

T X S T X S E when adding rst exceptions and then

exse

sideeects

Exercise For each of the monad transformer identify equational laws for the

new op erations sp ecied in and show that such laws are validated by the

new

translation For instance I validates the following equations

se

0 0 0

upd s in T S s upd s in l k p let s S let

T T T

0

upd s in upd s upd s T s s S let

T

0 0

T sl k p in upd s s S let

T T

0

X c T X let sl k p in c c T X

T

Exercise Semantics of Eects Given a monad T over the category of sets

Dene predicates for c T X S T X S corresp onding to the prop

erties c do es not read from S and c do es not write in S

notice that such predicates are extensional therefore a computation that

reads the state and then rewrites it unchanged is equivalent to a computa

tion that ignores the state

Dene a predicate for c T X T X E corresp onding to the prop erty

c do es not raise exceptions in E

Monads in Haskell

So far we have fo cussed on applications of monads in denotational semantics

but since Wadlers inuential pap ers in the early s they have also b ecome

part of the to olkit that Haskell programmers use on a day to day basis Indeed

monads have proven to b e so useful in practice that the language now includes

extensions sp ecically to make programming with them easy In the next few

sections we will see how monads are represented in Haskell lo ok at some of their

applications and try to explain why they have had such an impact

Implementing Monads in Haskell

The representation of monads in Haskell is based on the Kleisli triple formulation

recall Denition

A Kleisli triple over a category C is a triple T where T jC j

jC j A TA for A jC j f TA TB for f A TB and the

A

following equations hold

is In Haskell T corresp onds to a parameterised typ e is called return and

called This would suggest the following typ es

return a T a

a T b T a T b

where a and b are Haskell typ e variables so that these typ es are p olymorphic

But notice that we can consider to b e a curried function of two

with typ es a T b and T a In practice it is convenient to reverse these

arguments and instead give the typ e

T a a T b T b

Now the metalanguage notation let xe in e can b e conveniently expressed as

e x e

where x e is Haskells notation for xe Intuitively this binds x to the

result of e in e with this in mind we usually pronounce as bind

Example The monad of partiality can b e represented using the builtin

Haskell typ e

data Maybe a Just a Nothing

This denes a parameterised typ e Maybe whose elements are Just x for any

element x of typ e a representing a successful computation or Nothing repre

senting failure

The monad op erators can b e implemented as

return a Just a

m f case m of

Just a f a

Nothing Nothing

and failure can b e represented by

failure Nothing

As an example of an application a division function which op erates on p os

sibly failing integers can now b e dened as

divide Maybe Int Maybe Int Maybe Int

divide a b a m

b n

if n then failure

else return a div b

Try unfolding the calls of in this denition to understand the gain in clarity

that using monadic op erators brings

Example As a second example we show how to implement the monad of

sideeects in Haskell This time we will need to dene a new typ e State s a

to represent computations pro ducing an a with a sideeect on a state of typ e

s Haskell provides three ways to dene typ es

type State s a s sa

newtype State s a State s sa

data State s a State s sa

The rst alternative declares a type synonym State s a would b e in every

resp ect equivalent to the typ e s sa This would cause problems later

since many monads are represented by functions it would b e dicult to tell just

from the type which monad we were talking ab out

The second alternative declares State s a to b e a new typ e dierent from

all others but isomorphic to s sa The elements of the new typ e are

written State f to distinguish them from functions There is no need for the

tag used on elements to have the same name as the typ e but it is often convenient

to use the same name for b oth

The third alternative also declares State s a to b e a new typ e with elements

of the form State f but in contrast to newtype the State constructor is lazy

that is State and are dierent values This is b ecause data declarations

create lifted sumofpro duct typ es and even when the sum is trivial it is still

lifted Thus State s a is not isomorphic to s sa it has an extra

element and values of this typ e are more costly to manipulate as a result

We therefore cho ose the second alternative The monad op erations are now

easy to dene

return a State s sa

State m f State s let sa m s

State m f a

in m s

The state can b e manipulated using

readState State s s

readState State s ss

writeState s State s

writeState s State s

For example a function to increment the state could b e expressed using these

functions as

increment State Int

increment readState s

writeState s

The Monad Class Overloading return and Bind

Haskell programmers make use of many dierent monads it would b e awkward

if return and had to b e given dierent names for each one To avoid this

we use overloading so that the same names can b e used for every monad

Overloading in Haskell is supp orted via the class system overloaded names

are intro duced by dening a class containing them A class is essentially a signa

ture with a dierent implementation for each typ e The monad op erations are

a part of a class Monad whose denition is found in Haskells standard prelude

class Monad m where

return a m a

m a a m b m b

Here the class parameter m ranges over parameterised typ es read the declaration

as A parameterised typ e m is a Monad if it supp orts implementations of return

and with the given typ es

Implementations of these op erations are provided by making a corresp onding

instance declaration for example

instance Monad Maybe where

return a Just a

m f case m of

Just a f a

Nothing Nothing

which corresp onds to the denition of the Maybe monad given earlier For the

monad of sideeects we write

instance Monad State s where

return a State s sa

State m f State s let sa m s

State m f a

in m s

Notice that although we dened the typ e State with two parameters and the

Monad class requires a typ e with one parameter Haskell allows us to create the

typ e we need by partial ly applying the State typ e to one parameter typ es with

many parameters are curried Indeed we chose the order of the parameters in

the denition of State with this in mind

Now when the monadic op erators are applied the typ e at which they are

used determines which implementation is invoked This is why we were careful

to make State a new typ e ab ove

A great advantage of overloading the monad op erators is that it enables us

to write co de which works with any monad For example we could dene a

function which combines two monadic computations pro ducing integers into a

computation of their sum

addM a b a m

b n

return mn

Since nothing in this denition is sp ecic to a particular monad we can use this

function with any addM Just Just is Just but we could also use

addM with the State monad The typ e assigned to addM reects this it is

addM Monad m m Int m Int m Int

The Monad m is called a context and restricts the typ es which may b e

substituted for m to instances of the class Monad

Although addM is p erhaps to o sp ecialised to b e really useful we can derive a

very useful higherorder function by generalising over Indeed Haskells stan

dard Monad library provides a numb er of such functions such as

liftM Monad m a b m a m b

liftM Monad m a b c m a m b m c

sequence Monad m m a m a

With these denitions

addM liftM

Programming with monads is greatly eased by such a library

Exercise Give a denition of sequence The intention is that each compu

tation in the list is executed in turn and a list made of the results

Actually typ e inference pro duces an even more general typ e since the arithmetic is

also overloaded but we will gloss over this

Finally Haskell provides syntactic sugar for to make monadic programs

more readable the donotation For example the denition of addM ab ove could

equivalently b e written as

addM a b do m a

n b

return mn

The donotation is dened by

do e e

do x e e x do c

c

do e e do c

c

Applying these rules to the denition of addM ab ove rewrites it into the form

rst presented The donotation is simply a shorthand for bind but do es make

programs more recognisable esp ecially for b eginners

Example As an example of monadic programming consider the problem of

decorating the leaves of a tree with unique numb ers We shall use a parameterised

tree typ e

data Tree a Leaf a Bin Tree a Tree a

and dene a function

unique Tree a Tree aInt

which numb ers the leaves from upwards in lefttoright order For example

unique Bin Bin Leaf a Leaf b Leaf c

Bin Bin Leaf a Leaf b Leaf c

Intuitively we think of an integer state which is incremented every time a leaf is

encountered we shall therefore make use of the State monad to dene a function

unique Tree a State Int Tree aInt

First we dene a function to increment the state

tick State Int Int

tick do n readState

writeState n

return n

and then the denition of unique is straightforward

unique Leaf a do n tick

return Leaf an

unique Bin t t liftM Bin unique t unique t

Notice that we use liftM to apply the two function Bin to the results

of lab elling the two subtrees as a result the notational overhead of using a monad

is very small

Finally we dene unique to invoke the monadic function and supply an initial

state

unique t runState unique t

runState s State f snd f s

It is instructive to rewrite the unique function directly without using a

monad explicit state passing in the recursive denition clutters it signicantly

and creates opp ortunities for errors that the monadic co de completely avoids

Applying Monads

So far we have shown how monads are represented in Haskell and how the

language supp orts their use But what are monads used for Why have they

b ecome so prevalent in Haskell programs In this section we try to answer these

InputOutput the Killer Application

Historically inputoutput has b een awkward to handle in purely functional lan

guages The same applies to foreign function calls there is no way to guarantee

that a function written in C for example do es not have side eects so calling

it directly from a Haskell program would risk compromising Haskells purely

functional semantics

Yet it is clear enough that inputoutput can b e model led in a purely func

tional way we must just consider a program to b e a function from the state of

the universe b efore it is run to the state of the universe afterwards One p ossibil

ity is to write the program in this way every function dep ending on the external

state would take the universe as a parameter and every function mo difying it

would return a new universe as a part of its result For example a program to

copy one le to another might b e written as

copy String String Universe Universe

copy from to universe

let contents readFile from universe

universe writeFile to contents universe

in universe

Such a program has a purely functional semantics but is not easy to im

plement Of course we cannot really maintain several copies of the universe

at the same time and so functions such as writeFile must b e implemented

by actually writing the new contents to the lestore If the programmer then

accidentally or delib erately returns universe instead of universe as the

nal result of his program then the purely functional semantics is not correctly

implemented This approach has b een followed in Clean though using a linear

typ e system to guarantee that the programmer manipulates universes correctly

BS

However having seen monads we would probably wish to simplify the pro

gram ab ove by using a State monad to manage the universe By dening

type IO a State Universe a

and altering the typ es of the primitives slightly to

readFile String IO String

writeFile String String IO

then we can rewrite the le copying program as

copy String String IO

copy from to do contents readFile from

writeFile to contents

which lo oks almost like an imp erative program for the same task

This program is b oth purely functional and eciently implementable it is

quite safe to write the output le destructively However there is still a risk that

the programmer will dene inappropriate op erations on the IO typ e such as

snapshot IO Universe

snapshot State univ univ univ

The solution is just to make the IO type abstract JW This do es not change the

semantics of programs which remains purely functional but it does guarantee

that as long as all the primitive op erations on the IO typ e treat the universe in

a prop er singlethreaded way which all op erations implemented in imp erative

languages do then so do es any Haskell program which uses them

Since the IO monad was intro duced into Haskell it has b een p ossible to write

Haskell programs which do inputoutput call foreign functions directly and yet

still have a purely functional semantics Moreover these programs lo ok very

like ordinary programs in any imp erative language The contortions previously

needed to achieve similar eects are not worthy of description here

The reader may b e wondering what all the excitement is ab out here after all

it has b een p ossible to write ordinary imp erative programs in other languages

for a very long time including functional languages such as ML or Scheme what

is so sp ecial ab out writing them in Haskell Two things

The main dierence is that we read and write the entire contents of a le in one

op eration rather than bytebybyte as an imp erative program probably would This

may seem wasteful of space but thanks to lazy evaluation the characters of the

input le are only actually read into memory when they are needed for writing to

the output That is the space requirements are small and constant just as for a

bytebybyte imp erative program

Inputoutput can b e combined cleanly with the other features of Haskell

in particular higherorder functions p olymorphism and lazy evaluation Al

though ML for example combines inputoutput with the rst two the abil

ity to mix lazy evaluation cleanly with IO is unique to Haskell with monads

and as the copy example shows can lead to simpler programs than would

otherwise b e p ossible

Inputoutput is combined with a purely functional semantics In ML for

example any expression may p otentially have sideeects and transforma

tions which reorder computations are invalid without an eect analysis to

establish that the computations are sideeect free In Haskell no expres

sion has sideeects but some denote commands with eects moreover the

p otential to cause sideeects is evident in an expressions typ e Evaluation

order can b e changed freely but monadic computations cannot b e reordered

b ecause the monad laws do not p ermit it

PeytonJones excellent tutorial Pey covers this kind of monadic program

ming in much more detail and also discusses a useful renement to the semantics

presented here

Imp erative Algorithms

Many algorithms can b e expressed in a purely functional style with the same

complexity as their imp erative forms But some ecient algorithms dep end crit

ically on destructive up dates Examples include the FIND algorithm

many graph algorithms and the implementation of arrays with constant time

access and mo dication Without monads Haskell cannot express these algo

rithms with the same complexity as an imp erative language

With monads however it is easy to do so Just as the abstract IO monad en

ables us to write programs with a purely functional semantics and give them an

imp erative implementation so an abstract state transformer monad ST allows us

to write purely functional programs which up date the state destructively LJ

Semantically the typ e ST a is isomorphic to State Statea where State

is a function from typ ed references lo cations to their contents In the imple

mentation only one State ever exists which is up dated destructively in place

Op erations are provided to create read and write typ ed references

newSTRef a ST STRef a

readSTRef STRef a ST a

writeSTRef STRef a a ST

Here STRef a is the typ e of a containing a value of typ e a Other

op erations are provided to create and manipulate arrays

The reason for intro ducing a dierent monad ST rather than just providing

these op erations over the IO monad is that destructive up dates to variables in

While the IO monad is a part of Haskell the current standard JHe the

ST monad is not However every implementation provides it in some form the

description here is based on the Hugs mo dules ST and LazyST JRtYHG

a program are not external ly visible sideeects We can therefore encapsulate

these imp erative eects using a new primitive

runST ST a a

which semantically creates a new State runs its argument in it and discards

the nal State b efore returning an a as its result A corresp onding function

runIO would not b e implementable b ecause we have no way to discard the nal

Universe In the implementation of runST States are represented just by a

collection of references stored on the heap there is no cost involved in creating

a new one therefore Using runST we can write pure nonmonadic functions

whose implementation uses imp erative features internally

Example The depthrst search algorithm for graphs uses destructively up

dated marks to identify previously visited no des and avoid traversing them again

For simplicity let us represent graph no des by integers and graphs using the

typ e

type Graph Array Int Int

A graph is an array indexed by integers no des whose elements are the list

of successors of the corresp onding no de We can record which no des have b een

visited using an up dateable array of b o olean marks and program the depthrst

search algorithm as follows

dfs g ns runST do marks newSTArray bounds g

dfs g ns marks

dfs g marks return

dfs g nns marks

do visited readSTArray marks n

if visited then dfs g ns marks

else do writeSTArray marks n True

ns dfs g gnns marks

return nns

The function dfs returns a list of all no des reachable from the given list of ro ots

in depthrst order for example

dfs array

The type of the depthrst search function is

dfs Graph Int Int

It is a pure nonmonadic function which can b e freely mixed with other non

monadic co de

Imp erative features combine interestingly with lazy evaluation In this ex

ample the output list is pro duced lazily the traversal runs only far enough to

pro duce the elements which are demanded This is p ossible b ecause in the co de

ab ove return nns can pro duce a result before ns is known The recursive

call of dfs need not b e p erformed until the value of ns is actually needed

Thus we can eciently use dfs even for incomplete traversals to search for the

rst no de satisfying p for example we can use

head filter p dfs g roots

safe in the knowledge that the traversal will stop when the rst no de is found

King and Launchbury have shown how the lazy depthrst search function

can b e used to express a wide variety of graph algorithms b oth elegantly and

eciently KL

The ST monad raises some interesting typing issues Note rst of all that

its op erations cannot b e implemented in Haskell with the typ es given even

ineciently The problem is that we cannot represent an indexed collection of

values with arbitrary typ es if we tried to represent States as functions from

references to contents for example then all the contents would have to have the

same typ e A purely functional implementation would need dependent types to

allow the typ e of a references contents to dep end on the reference itself Thus

the ST monad gives the Haskell programmer indirect access to dep endent typ es

and indeed sometimes other applications which require dep endent typ es can b e

programmed in terms of ST

Secondly we must somehow prevent references created in one State b eing

used in another it would b e hard to assign a sensible meaning to the result

This is done by giving the ST typ e an additional parameter which we may think

of as a state identier ST s a is the typ e of computations on state s pro ducing

an a Reference typ es are also parameterised on the state identier so the typ es

of the op erations on them b ecome

newSTRef a ST s STRef s a

readSTRef STRef s a ST s a

writeSTRef STRef s a a ST s

These typ es guarantee that ST computations only manipulate references lying

in their State

But what should the typ e of runST b e It is supp osed to create a new State

to run its argument in but if we give it the typ e

runST ST s a a

then it will b e applicable to any ST computation including those which ma

nipulate references in other States To prevent this runST is given a rank

polymorphic typ e

runST forall s ST s a a

Hugs actually provides two variations on the ST monad with and without lazy b e

haviour The programmer cho oses b etween them by imp orting either ST or LazyST

and Hugs has b een extended with rank p olymorphism just to make this p os

sible This typ e ensures that the argument of runST can safely b e run in any

State in particular the new one which runST creates

Example The expression

runST newSTRef

is not welltyp ed Since newSTRef has the typ e ST s STRef s Int then

runST would have to pro duce a result of typ e STRef s Int but the scop e of

s do es not extend over the typ e of the result

Example The expression

runST do rnewSTRef

return runST readSTRef r

is not welltyp ed either b ecause the argument of the inner runST is not p oly

morphic it dep ends on the state identier of the outer one

The inclusion of the ST monad and assignments in Haskell raises an interest

ing just what is a purely functional language Perhaps the answer is

one in which assignment has a funny typ e

Domain Sp ecic Emb edded Languages

Since the early days of functional programming combinator libraries have b een

used to dene succinct notations for programs in particular domains Bur

There are combinator libraries for many dierent applications but in this section

we shall fo cus on one very wellstudied area parsing A library for writing parsers

typically denes a typ e Parser a of parsers for values of typ e a and combinators

for constructing and invoking parsers These might include

satisfy Char Bool Parser Char

to construct a parser which accepts a single character satisfying the given pred

icate

Parser a Parser a Parser a

to construct a parser which accepts an input if either of its op erands can parse

it and

runParser Parser a String a

to invoke a parser on a given input

A parsing library must also include combinators to run parsers in sequence

and to build parsers which invoke functions to compute their results Wadler

realised that these could b e provided by declaring the Parser typ e to b e a monad

Wad Further combinators can then b e dened in terms of these basic ones

such as a combinator accepting a particular character

literal Char Parser Char

literal c satisfy c

and a combinator for rep etition

many Parser a Parser a

many p liftM p many p return

which parses a list of any numb er of ps

Given such a library parsing programs can b e written very succinctly As

an example we present a function to evaluate arithmetic expressions involving

addition and multiplication

eval String Int

eval runParser expr

expr do t term

literal

e expr

return te

term

term do c closed

literal

t term

return ct

closed

closed do literal

e expr

literal

return e

numeral

numeral do ds many satisfy isDigit

return read ds

With a go o d choice of combinators the co de of a parser closely resembles the

grammar it parses

In recent years a dierent view of such combinator libraries has b ecome

p opular we think of them as dening a domain specic language DSL whose

In practice the resemblance would b e a little less close real parsers for arithmetic ex

pressions are leftrecursive use a lexical analyser and are written to avoid exp ensive

backtracking On the other hand real parsing libraries provide more combinators to

handle these features and make parsers even more succinct See HM for a go o d

description

Notice how imp ortant Haskells lazy evaluation is here without it these recursive

denitions would not make sense

constructions are the combinators of the library Hud With this view this

little parsing library denes a programming language with sp ecial constructions

to accept a symb ol and to express alternatives

Every time a functional programmer designs a combinator library then we

might as well say that he or she designs a domain sp ecic programming lan

guage integrated with Haskell This is a useful p ersp ective since it encourages

programmers to pro duce a mo dular design with a clean separation b etween the

semantics of the DSL and the program that uses it rather than mixing com

binators and raw semantics willynilly And since monads app ear so often in

programming language semantics it is hardly surprising that they app ear often

in combinator libraries also

We will return to the implementation of the parsing library in the next sec

tion after a discussion of monad transformers

Monad Transformers in Haskell

The Haskell programmer who makes heavy use of combinators will need to im

plement a large numb er of monads Although it is p erfectly p ossible to dene

a new typ e for each one and implement return and from scratch it saves

lab our to construct monads systematically where p ossible The monad trans

formers of section oer an attractive way of doing so as Liang Hudak and

Jones p oint out LHJ

Recall the denition

A monad transformer is a function F jM onC j jM onC j ie a

function mapping monads over a category C to monads We are inter

ested in monad transformers for adding computational eects therefore

we require that for any monad T there should b e a monad morphism

in T FT

T

We represent monad transformers in Haskell by typ es parameterised on a monad

itself a parameterised typ e and the result typ e that is typ es of kind

For example the partiality monad transformer is rep

resented by the typ e

newtype MaybeT m a MaybeT m Maybe a

According to the denition MaybeT m should b e a monad whenever m is which

we can demonstrate by implementing return and

instance Monad m Monad MaybeT m where

return x MaybeT return Just x

MaybeT m f

MaybeT do x m

case x of

Nothing return Nothing

Just a let MaybeT m f a in m

Moreover according to the denition of a monad transformer ab ove there should

also b e a monad morphism from m to MaybeT m that is it should b e p ossible

to transform computations of one typ e into the other Since we need to de

ne monad morphisms for many dierent monad transformers we use Haskells

overloading again and intro duce a class of monad transformers

class Monad m Monad t m MonadTransformer t m where

lift m a t m a

Here t is the monad transformer m is the monad it is applied to and lift is

the monad morphism Now we can make MaybeT into an instance of this class

instance Monad m MonadTransformer MaybeT m where

lift m MaybeT do x m

return Just x

The purp ose of the MaybeT transformer is to enable computations to fail we

shall intro duce op erations to cause and handle failures One might exp ect their

typ es to b e

failure MaybeT m a

handle MaybeT m a MaybeT m a MaybeT m a

However this is not go o d enough since we exp ect to combine MaybeT with other

monad transformers the monad we actually want to apply these op erations

at may well b e of some other form but as long as it involves the MaybeT

transformer somewhere we ought to b e able to do so

We will therefore overload these op erations also and dene a class of Maybe

like monads

class Monad m MaybeMonad m where

failure m a

handle m a m a m a

Of course monads of the form MaybeT m will b e instances of this class but later

we will also see others In this case the instance declaration is

instance Monad m MaybeMonad MaybeT m where

failure MaybeT return Nothing

MaybeT m handle MaybeT m

MaybeT do x m

case x of

Nothing m

Just a return Just a

Here we step outside Haskell by using a multiple parameter class an extension

which is however supp orted by Hugs and many other implementations We make

m a parameter of the class to p ermit the denition of monad transformers which

place additional requirements on their argument monad

Usually the standard Haskell class MonadPlus with op erations mzero and mplus is

used in this case but in the present context the names Mayb eMonad failure and

handle are more natural

Finally we need a way to run elements of this typ e We dene

runMaybe Monad m MaybeT m a m a

runMaybe MaybeT m do x m

case x of

Just a return a

for this purp ose We leave undened how we run an erroneous computation

thus converting an explicitly represented error into a real Haskell one

We have now seen all the elements of a monad transformer in Haskell To

summarise

We dene a typ e to represent the transformer say TransT with two param

eters the rst of which should b e a monad

We declare TransT m to b e a Monad under the assumption that m already

is

We declare TransT to b e an instance of class MonadTransformer thus den

ing how computations are lifted from m to TransT m

We dene a class TransMonad of Translike monads containing the op era

tions that it is TransTs purp ose to supp ort

We declare TransT m to b e an instance of TransMonad thus showing that it

do es indeed supp ort them

We dene a function to run TransT mcomputations which pro duces

mcomputations as a result In general runTrans may need additional pa

rameters for example for a state transformer we probably want to supply

an initial state

We can carry out this program to dene monad transformers for among others

state transformers represented by

newtype StateT s m a StateT s m s a

supp orting op erations in the class

class Monad m StateMonad s m m s where

readState m s

writeState s m

environment readers represented by

newtype EnvT s m a EnvT s m a

supp orting op erations in the class

This class declaration uses Mark Jones functional dependencies supp orted by Hugs

to declare that the typ e of the monads state is determined by the typ e of the monad

itself In other words the same monad cannot have two dierent states of dierent

typ es While not strictly necessary making the dep endency explicit enables the

typ echecker to infer the typ e of the state much more often and helps to avoid

hardtounderstand error messages ab out ambiguous typings

class Monad m EnvMonad env m m env where

inEnv env m a m a

rdEnv m env

where rdEnv reads the current value of the environment and inEnv runs its

argument in the given environment

continuations represented by

newtype ContT ans m a ContT a m ans m ans

supp orting op erations in the class

class Monad m ContMonad m where

callcc a m b m a m a

where callcc f calls f passing it a function k which if it is ever called

terminates the call of callcc immediately with its argument as the nal

result

Two steps remain b efore we can use monad transformers in practice Firstly

since monad transformers only transform one monad into another we must dene

a monad to start with Although one could start with any monad it is natural

to use a vanilla monad with no computational features the identity monad

newtype Id a Id a

The implementations of return and on this monad just add and remove the

Id tag

Secondly so far the only instances in class MaybeMonad are of the form

MaybeT m the only instances in class StateMonad of the form StateT s m and

so on Yet when we combine two or more monads of course we exp ect to use the

features of both in the resulting monad For example if we construct the monad

StateT s MaybeT Id then we exp ect to b e able to use failure and handle

at this typ e as well as readState and writeState

The only way to do so is to give further instance declarations which dene

how to lift the op erations of one monad over another For example we can lift

failure handling to state monads as follows

instance MaybeMonad m MaybeMonad StateT s m where

failure lift failure

StateT m handle StateT m StateT s m s handle m s

Certainly this requires O n instance declarations one for each pair of monad

transformers but there is unfortunately no other solution

The payo for all this work is that when we need to dene a monad we can

often construct it quickly by comp osing monad transformers and automatically

inherit a collection of useful op erations

Example We can implement the parsing library from section by combin

ing state transformation with failure We shall let a parsers state b e the input

to b e parsed running a parser will consume a part of it so running two parsers

in sequence will parse successive parts of the input Attempting to run a parser

may succeed or fail and we will often wish to handle failures by trying a dierent

parser instead We can therefore dene a suitable monad by

type Parser a StateT String MaybeT Id a

whose computations we can run using

runParser p s runId runMaybe runState s p

It turns out that the op erator we called earlier is just handle and satisfy

is simply dened by

satisfy s Bool Parser s s

satisfy p do sreadState

case s of

failure

xxs if p x then do writeState xs

return x

else failure

There is no more to do

Monads and DSLs a Discussion

It is clear why monads have b een so successful for programming IO and im

p erative algorithms in Haskell they oer the only really satisfactory solution

But they have also b een widely adopted by the designers of combinator libraries

Why We have made the analogy b etween a combinator library and a domain

sp ecic language and since monads can b e used to structure denotational se

mantics it is not so surprising that they can also b e used in combinator libraries

But that something can b e used do es not mean that it wil l b e used The de

signer of a combinator library has a choice he need not slavishly follow the One

Monadic Path why then have so many chosen to do so What are the over

whelming practical b enets that ow from using monads in combinator library

design in particular

Monads oer signicant advantages in three key areas Firstly they oer a

design principle to follow A designer who wants to capture a particular func

tionality in a library but is unsure exactly what interface to provide to it can b e

reasonably condent that a monadic interface will b e a go o d choice The monad

interface has b een tried and tested we know it allows the library user great

exibility In contrast early parsing libraries for example used nonmonadic

interfaces which made some parsers awkward to write

Secondly monads can guide the implementation of a library A library de

signer must cho ose an appropriate typ e for his combinators to work over and his

task is eased if the typ e is a monad Many monad typ es can b e constructed sys

tematically as we have seen in this section and so can some parts of the library

which op erate on them Given a collection of monad transformers substantial

parts of the library come for free just as when we found there was little left

to implement after comp osing the representation of Parsers from two monad

transformers

Thirdly there are b enets when many libraries share a part of their inter

faces Users can learn to use each new library more quickly b ecause the monadic

part of its interface is already familiar Because of the common interface it is

reasonable to dene generic monadic functions such as liftM which work with

any monadic library This b oth helps users who need only learn to use liftM

once and greatly eases the task of implementors who nd much of the func

tionality they want to provide comes for free And of course it is thanks to the

widespread use of monads that Haskell has b een extended with syntactic sugar

to supp ort them if each library had its own completely separate interface

then it would b e impractical to supp ort them all with sp ecial syntax

Taken together these are comp elling reasons for a library designer to cho ose

monads whenever p ossible

Exercises on Monads

This section contains practical exercises intended to b e solved using Hugs on

a computer Since some readers will already b e familiar with Haskell and will

have used monads already while others will b e seeing them for the rst time

the exercises are divided into dierent levels of diculty Cho ose those which

are right for you

The Hugs interpreter is started with the command

hugs

The ag informs hugs that extensions to Haskell should b e allowed and

they are needed for some of these exercises When Hugs is started it prompts for

a command or an expression to evaluate the command lists the commands

available Hugs is used by placing denitions in a le loading the le into the

interpreter with the l or r command and typing expressions to evaluate

You can obtain information on any dened name with the command i and

discover which names are in scop e using n followed by a regular expression

matching the names you are interested in Do not try to typ e denitions in

resp onse to the interpreters prompt they will not b e understo o d

Easy Exercises

Cho ose these exercises if you were previously unfamiliar with monads or Haskell

Exercise Write a function

dir IO String

which returns a list of the le names in the current directory You can obtain

them by running ls and placing the output in a le which you then read You

will need to imp ort mo dule System which denes a function system to execute

shell commands place import System on the rst line of your le A string

can b e split into its constituent words using the standard function words and

you can print values for testing using the standard function print

Exercise Write a function

nodups String String

which removes duplicate elements from a list of strings the intention is to

return a list of strings in the argument in order of rst o ccurrence It is easy

to write an inecient version of no dups which keeps a list of the strings seen

so far but you should use a hash table internally so that each string in the

input is compared against only a few others The choice of hash function is not

particularly imp ortant for this exercise though Moreover you should pro duce

the result list lazily Test this by running

interact unlines nodups lines

which should echo each line you then typ e on its rst o ccurrence

You will need to use Haskell lists which are written by enclosing their ele

ments in square brackets separated by commas and the cons op erator which

is Imp ort mo dule LazyST and use newSTArray to create your hash table

readSTArray to read it and writeSTArray to write it Beware of Haskells lay

out rule which insists that every expression in a do b egin in the same column

and interprets everything app earing in that column as the start of a new

expression

Exercise The implementation of the MaybeT transformer is given ab ove but

the implementations of the StateT EnvT and ContT transformers were only

sketched Complete them ContT is quite dicult and you might want to leave

it for later

Exercise We dene the MaybeT typ e by

newtype MaybeT m a MaybeT m Maybe a

What if we had dened it by

newtype MaybeT m a MaybeT Maybe m a

instead Could we still have dened a monad transformer based on it

Exercise We dened the typ e of Parsers ab ove by

type Parser a StateT String MaybeT Id a

What if we had combined state transformation and failure the other way round

type Parser a MaybeT StateT String Id a

Dene an instance of StateMonad for MaybeT and investigate the b ehaviour of

several examples combining failure handling and sideeects using each of these

two monads Is there a dierence in their b ehaviour

Mo derate Exercises

Cho ose these exercises if you are comfortable with Haskell and have seen monads

b efore

Exercise Implement a monad MaybeST based on the builtin ST monad

which provides up dateable typ ed references but also supp orts failure and failure

handling If m fails in m handle h then all references should contain the same

values on entering the handler h that they had when m was entered

Can you add an op erator

commit MaybeST

with the prop erty that up dates b efore a commit survive a subsequent failure

Exercise A dierent way to handle failures is using the typ e

newtype CPSMaybe ans a

CPSMaybe a ans ans ans ans

This is similar to the monad of continuations but b oth computations and con

tinuations take an extra argument the value to return in case of failure When

a failure o ccurs this argument is returned directly and the normal

is not invoked

Make CPSMaybe an instance of class Monad and MaybeMonad and dene

runCPSMaybe

Failure handling programs often use a great deal of space b ecause failure

handlers retain data that is no longer needed in the successful execution Yet

once one branch has progressed suciently far we often know that its failure

handler is no longer relevant For example in parsers we usually combine parsers

for quite dierent constructions and if the rst parser succeeds in parsing more

than a few tokens then we know that the second cannot p ossibly succeed Can

you dene an op erator

cut CPSMaybe ans

which discards the failure handler so that the memory it o ccupies can b e re

claimed How would you use cut in a parsing library

Dicult Exercises

These should give you something to get your teeth into

Exercise Implement a domain sp ecic language for concurrent programming

using a monad Process s a and typ ed channels Chan s a with the op erations

chan Process s Chan s a

send Chan s a a Process s

recv Chan s a Process s a

to create channels and send and receive messages synchronously

fork Process s a Process s

to start a new concurrent task and

runProcess forall s Process s a a

to run a pro cess By analogy with the ST monad s is a statethread identi

er which is used to guarantee that channels are not created in one call of

runProcess and used in another You will need to write the typ e of runProcess

explicitly Hugs cannot infer rank typ es

Exercise provides socalled logical variables whose values can b e re

ferred to b efore they are set Dene a typ e LVar and a monad Logic in terms

of ST supp orting op erations

newLVar Logic s LVar s a

readLVar LVar s a a

writeLVar LVar s a a Logic s

where s is again a statethread identier The intention is that an LVar should b e

written exactly once but its value may b e read beforehand b etween its creation

and the write lazy evaluation is at work here Note that readLVar do es not

have a monadic typ e and so can b e used anywhere Of course this can only

work if the value written to the LVar do es not dep end on itself Hint You will

need to use

fixST a ST s a ST s a

to solve this exercise fixST x m binds x to the result pro duced by m

during its own computation

Exercise In some applications it is useful to dump the state of a program

to a le or send it over a network so that the program can b e restarted in the

same state later or on another machine Dene a monad Interruptable with

an op eration

dump Interruptable

which stops execution and converts a representation of the state of the program

to a form that can b e saved in a le The result of running an Interruptable

computation should indicate whether or not dumping o ccurred and if so provide

the dump ed state If s is a state dump ed by a computation m then resume m s

should restart m in the state that s represents Note that m might dump several

times during its execution and you should b e able restart it at each p oint

You will need to cho ose a representation for states that can include every

typ e of value used in a computation To avoid typing problems convert values

to strings for storage using show

You will not b e able to make Interruptable an instance of class Monad

b ecause your implementations of return and will not b e suciently p oly

morphic they will only work over values that can b e converted to strings

This is unfortunate but you can just cho ose other names for the purp oses of

this exercise One solution to the problem is describ ed in Hug

Intermediate Languages for Compilation

We have seen how monads may b e used to structure the denotational semantics

of languages with implicit computational eects and how they may b e used to

express and control the use of computational eects in languages like Haskell in

which the only implicit eect is the p ossibility of nontermination We now turn

to the use of monads in the practical compilation of languages such as ML with

implicit side eects Much of this material refers to the MLj compiler for Stan

dard ML BKR and its intermediate language MIL Monadic Intermediate

Language BK

Compilation by Transformation

It should not b e a surprise that ideas which are useful in structuring seman

tics also turn out to b e useful in structuring the internals of compilers since by

implementing rules for deriving program equivalences there is a sense in which

compilers actually do semantics Even in the absence of sophisticated static anal

yses compilers for functional languages typically work by translating the users

program into an intermediate form and then p erforming a sequence of rewrites

on the intermediate representation b efore translating that into lowerlevel co de

in the backend These rewrites are intended to preserve the semantics ie the

observable b ehaviour of the users program whilst improving the eciency of

the nal program in terms of execution sp eed dynamic memory usage andor

co de size Hence the rewriting rules used by the compiler should b e observa

tional equivalences and if they are applied lo cally ie indep endently of the

surrounding context then they should b e instances of an observational congru

ence relation Of course the hard part is that the compiler also has to decide

when applying a particular semantic equation is likely to b e an improvement

Intermediate Languages

The reasons for having an intermediate language at all rather than just doing

rewriting on the abstract syntax tree of the source program include

Complexity Source languages tend to have many sophisticated syntactic

forms eg nested patterns or list comprehensions which are convenient for

the programmer but which can b e translated into a simpler core language

leaving fewer cases for the optimizer and co de generator to deal with

Level Many optimizing transformations involve choices which cannot b e

expressed in the source language b ecause they are at a lower level of ab

straction In other words they involve distinctions b etween implementation

details which the source language cannot make For example

All functions in ML take a single argument if you want to pass more

than one then you package them up as a single tuple This is simple

and elegant for the programmer but we dont want the compiled co de

to pass a p ointer to a fresh heapallo cated tuple if it could just pass

a couple of arguments on the stack or in registers Hence MIL like

other intermediate languages for ML includes b oth tuples and multiple

arguments and transforms some instances of the former into the latter

MIL also includes datastructures with holes ie uninitialized values

These are used to express a transformation which turns some nontail

calls into tail calls and have linear typing rules which prevent holes b eing

dereferenced or lled more than once Min

Of course there are many levels of abstraction b etween the source and target

languages so it is common for compilers to use several dierent intermediate

languages at dierent phases

However in these notes we shall not b e concerned so much with the com

plexity of realistic source languages or with expressing lowlevel implementation

details in intermediate languages Instead we will b e interested in the slightly

more nebulous idea that a go o d intermediate language may b e more uniform

expressive and explicit than the source

Many imp ortant transformations do not involve concepts which are essen

tially at a lowerlevel level of abstraction than the source language but can

nevertheless b e anywhere b etween b othersome and imp ossible to express or im

plement directly on the source language syntax

The equational theory of even a simplied core of the source language may

b e messy and illsuited to optimization by rewriting Rather than have a com

plex rewriting system with conditional rewrites dep ending on various kinds of

contextual information one can often achieve the same end result by translat

ing into an intermediate language with a b etterb ehaved equational theory It

is typically the case that a cleaner intermediate language makes explicit some

asp ects of b ehaviour which are implicit in the source language Examples

Many intermediate languages intro duce explicit names for every intermediate

value Not only are the names useful in building various auxiliary datastruc

tures but they make it easy to for example share sub expressions A very

trivial case would b e

let val x

in x x

end

which we dont want to simplify to the equivalent

b ecause that allo cates two identical pairs One particularly straighforward

way to get a b etter result is to only allow intro ductions and eliminations to

b e applied to variables or atomic constants so the translation of the original

program into the intermediate form is

Or to have one allencompassing intermediate datatyp e but the ensure that the

input and output of each phase satisfy particular additional constraints

Which can make such intermediate representations larger than the corresp onding source

let val y

in let val x y

in x x

end

end

which rewrites to

let val y

in let val x y

in y y

end

end

and then to

let val y

in y y

end

which is probably what we wanted

MIL contains an unusual exceptionhandling construct b ecause SMLs handle

construct is unable to express some commuting conversionstyle rewrites

which we wished to p erform BK

Some compilers for higherorder languages use a continuation passing style

CPS lamb dacalculus as their intermediate language see for example

AppKKR There are translations of call by value CBV and call

by name CBN source languages into CPS Once a program is in CPS it

is sound to apply the full unrestricted rules rather than say the more

restricted rules which are valid for the CBV lamb da calculus

v v v

Moreover as Plotkin shows in his seminal pap er Plo and on CPS

terms prove strictly more equivalences b etween translated terms than do

v

and on the corresp onding terms Hence a compiler for a CBV language

v v

which translates into CPS and uses can p erform more transformations

than one which just uses and on the source syntax

v v

CPS transformed terms make evaluation order explict which makes them

easier to compile to lowlevel imp erative co de in the backend allow tailcall

elimination b e b e expressed naturally and are particularly natural if the

language contains callcc or other sophisticated control op erators

However Flanagan et al FSDF argue that compiling CBV lamb da

calculus via CPS is an unnecessarily complicated and indirect technique

The translation intro duces lots of new abstractions and new essentially

trivial administrative redexes To generate go o d co de and to identify ad

ministrative redexes real CPS compilers treat abstractions intro duced by

the translation pro cess dierently from those originating in the original pro

gram and eectively undo the CPS translation in the backend after having

p erformed transformations Flanagan et al show that the same eect can b e

obtained by using a calculus with let and p eforming Areductions to reach

an Anormal form Areductions were intro duced in SF and are dened

in terms of evaluation contexts Amongst other things Anormal forms name

all intermediate values and only apply eliminations to variables or values

An example of an Areduction is the following

E if V then N else N if V then E N else E N

where E is an evaluation context Flanagan et al observe that most non

CPS direct style compilers p erform some Areductions in a moreorless

ad ho c manner and suggest that doing all of them and so working with

Anormal forms is b oth more uniform and leads to faster co de

Typ ed Intermediate Languages One big decision when designing an inter

mediate language is whether or not it should b e typ ed Even when the source

language has strong static typ es many compilers discard all typ es after they

have b een checked and work with an untyp ed intermediate language More

recently typ ed intermediate languages have b ecome much more p opular in com

pilers and in the fashionable area of mobile co de security Examples of typ ed

compiler intermediate languages include FLINT Sha the GHC intermediate

language Jon and MIL The advantages of keeping typ e information around

in an intermediate language include

Typ es are increasingly the basis for static analyses optimizing transforma

tions and representation choices Typ ebased optimization can range from

the use of sophisticated typ e systems for static analyses to exploitation of

the fact that static typ es in the source language provide valuable information

which it would b e fo olish to ignore or recompute For example the fact that

in many languages p ointers to ob jects of dierent typ es can never alias can

b e used to allow more transformations The MLj compiler uses simple typ e

information to share representations using a single Java class to implement

several dierent ML closures

Typ e information can b e used in generating backend co de for example in

interfacing to a garbage collector or allo cating registers

Typ echecking the intermediate representation is a very go o d way of nding

compiler bugs

Its particularly natural if the language allows typ es to b e reected as values

Its clearly the right thing to do if the target language is itself typ ed This is

the case for MLj since Java byteco de is typ ed and for compilers targetting

typ ed assembly language MWCG

But there are disadvantages to o

Keeping typ e information around and maintaining it during transformations

can b e very exp ensive in b oth space and time

And this really is a signicant advantage

Unless the typ e system is complex andor rather nonstandard restricting

the compiler to work with typable terms can prohibit transformations Even

something like closureconversion packaging functions with the values of

their free variables is not trivial from the p oint of view of typing MMH

ML as a Compiler Intermediate Language Several researchers have sug

T

gested that Moggis computational metalanguage ML MogMog might

T

b e useful as the basis of a typ ed intermediate language

Benton Ben prop osed the use of the computational metalanguage as a

way of expressing the optimizations which may b e p erformed as a result of

strictness analysis in compilers for CBN languages such as Haskell Earlier work

on expressing the use of strictness analysis was largely in terms of a somewhat

informal notion of changes in evaluation strategy for xed syntax It is much

more elegant to reason ab out changes in translation of the source language into

some other language which itself has a xed op erational semantics In the case

of a pure CBN source language such as PCF Plo however one cannot

directly use a sourcetosource translation to express strictnessbased transfor

mations Adding a strict let construct with typing rule

M A x A N B

let x M in N B

where let x M in N rst evaluates M to Weak Head Normal Form WHNF

b efore substituting for x in N allows one to express basic strictness optimiza

tions such as replacing the application M N with let x N in M x when

M is known to b e strict But this is only half the story wed also like to b e

able to p erform optimizations based on the fact that certain expressions such

as x in our example are known to b e b ound to values in WHNF and so need

not b e represented by thunks or reevaluated To capture this kind of informa

tion Benton suggested a variant of the computational metalanguage in which

an expression of a value typ e A is always in WHNF and the computation typ e

TA is used for p otentially unevaluated expressions which if they terminate will

yield values of typ e A The default translation of a callbyname expression of

typ e A B is then to an intermediate language expression of typ e of typ e

n n n

T A B T TA TB ie a computation pro ducing a function from

computations to computations An expression denoting a strict function which is

only called in strict contexts by contrast can b e translated into an intermediate

n n

language term of typ e T A TB a computation pro ducing a function from

values to computations

Exercise The standard denotational semantics of PCF is in the CCC of

p ointed cp os and continuous maps with int Z and function space inter

A

preted by A B B This semantics is adequate for a CBN op erational

The author like several others p ersistently refers to ML as the computational

T

although Moggi actually invented that name for his a dier

c

ent calculus without computational typ es This do esnt seem to have ever caused

terrible confusion but one should b e aware of it

semantics in which the notion of observation is termination of closed terms of

ground typ e It seems natural that one could give a semantics to PCF with a

strict let construct just by dening

if M

let x M in N

N x M otherwise

but in fact the semantics is then no longer adequate Why How might one

mo dify the semantics to x the problem How go o d is the mo died semantics

as a semantics of the original language ie without let

Other authors addressed the problem of expressing strictnessbased trans

formations by varying a translation of the source language into continuation

passing style BMDH The two strands of work were then brought to

gether by Danvy and Hatcli HD who showed how various CPS transforms

could b e factored through translations into the computational metalanguage and

how the administrative reductions of CPS and Flanagan et als Areductions

corresp onded to applying the reduction and commuting conversions see Sec

tion asso ciated with the computation typ e constructor in the computational

metalanguage Danvy and Hatcli also suggest that the computational metalan

guage could make an attractive compiler intermediate language

Peyton Jones et al JLST prop osed the use of an intermediate language

based on the computational metalanguage as a common framework for compiling

b oth callbyvalue and callbyname languages Barthe et al BHT add

computational typ es to the pure typ e systems PTS to obtain monadic versions

of a whole family of higherorder typ ed lamb da calculi such as F and the

Calculus of Constructions and advo cate the use of such calculi as compiler

intermediate languages for languages which combine p olymorphic typ e andor

mo dule systems with sideeects

Typ e and Eect Systems

Intro duction

The work referred to in the previous section concerns using a wellb ehaved inter

mediate language Anormal forms CPS or ML to p erform sound rewriting

T

on a programs written in languages with impure features All those interme

diate languages make some kind of separation in the typ e system andor the

language syntax b etween pure values and impure p otentially sideeecting

computations The separation is however fairly crude and there are often go o d

reasons for wanting to infer at compiletime a safe approximation to just which

Unfortunately JLST contains an error the semantics of the intermediate lan

guage L do es not actually satisfy the monad equations

As is always the case with static analyses precise information is uncomputable so

we have to settle for approximations In this case that means overestimating the

p ossible sideeects of an expression

sideeects may happ en as a result of evaluating a particular expression This

kind of eect analysis is really only applicable to CBV languages since CBN

languages do not usually allow any sideeects other than nontermination

Historically the rst eect analyses for higher order languages were develop ed

to avoid a typ e soundness problem which o ccurs when p olymorphism is combined

naively with up dateable references To see the problem consider the following

illegal SML program

let val r ref fn x x

in r fn nn

r true

end

Using the obvious extension of the HindleyMilner typ e inference rules to cover

reference creation dereferencing and assignment the program ab ove would typ e

check

fn xx has typ e so

ref fn xx has typ e ref

generalization then gives r the typ e scheme ref

so by sp ecialization r has typ e int intref meaning the assignment

typ echecks

and by another sp ecialization r has typ e bool boolref so

r has typ e bool bool so the application typ e checks

However it is clear that the program really has a typ e error as it will try to

increment a b o olean

To get around this problem Giord Lucassen Jouvelot Talpin and others

GLGJLSTJ develop ed type and eect systems The idea is to have a

rened typ e system which infers b oth the typ e and the p ossible eects which an

expression may have and to restrict p olymorphic generalization to typ e variables

which do not app ear in sideeecting expressions In the example ab ove one

would then infer that the expression ref fn xx creates a new reference cell

of typ e This prevents the typ e of r b eing generalized in the let rule

so the assignment causes to b e unied with int and the application of r to

true then fails to typ echeck

It should b e noted in passing that there are a numb er of dierent ways

of avoiding the typ e lo ophole For example Toftes imp erative typ e discipline

Tof using imp erative typ e variables was used in the old version of the

Standard ML Denition whilst Leroy and Weis prop osed a dierent scheme for

tracking dangerous typ e variables those app earing free in the typ es of expres

sions stored in references LW A key motivation for most of that work was

Dep ending on the order in which the inference algorithm works the application

might alternatively cause to b e unied with bool and then the error would b e

discovered in the assignment This is an example of why giving go o d typ e error

messages is hard

to allow as much p olymorphic generalization as p ossible to happ en in the let

rule whilst still keeping the typ e system sound However exp ensive and unpre

dictable inference systems which have a direct impact on which user programs

actually typ echeck are not often a go o d idea In Wright published a study

Wri indicating that nearly all existing SML co de would still typ echeck and

run identically sometimes mo dulo a little expansion if p olymorphic general

ization were simply restricted to source expressions which were syntactic values

and thus trivially sideeect free This simple restriction was adopted in the

revised SML Denition and research into fancy typ e systems for impure

p olymorphic languages seems to have now essentially ceased

However there are still very go o d reasons for wanting to do automatic ef

fect inference The most obvious is that more detailed eect information allows

compilers to p erform more aggressive optimizations Other applications include

various kinds of verication to ol either to assist the programmer or to check

security p olicies for example In SML even a seemingly trivial rewrite such as

the deadco de elimination

let val x M in M end M x FV M

is generally only valid if the evaluation of M do esnt diverge p erform IO

up date the state or throw an exception though it is still valid if M reads from

reference cells or allo cates new ones

The Basic Idea

There are now many dierent typ e and eect systems in the literature but they

all share a common core The b o ok NHH contains amongst other things

a fair amount on eect systems and many more references than these notes A

traditional typ e system infers judgements of the form

x A x A M B

n n

where the A and B are typ es A typ e and eect system infers judgements of

i

the form

x A x A M B

n n

which says that in the given typing context the expression M has typ e B and

eect The eect is drawn from some set E whose elements denote sets of

actual eects which may o ccur at runtime in other words they are abstractions

of runtime eects just as typ es are abstractions of runtime values Exactly what

is in E dep ends not only on what runtime eects are p ossible in the language

but also on how precise one wishes to make the analysis The simplest nontrivial

eect system would simply take E to have two elements one usually written

The reader who thinks that this is a silly example b ecause programmers never write

co de like that is quite mistaken Immediately unused bindings may not b e common

in the original source but they are frequently created as a result of other rewrites

denoting no eect at all pure and the other just meaning p ossibly has some

eect Most eect systems are as we shall see a little more rened than this

The rst thing to remark ab out the form of a typ e and eect judgement is

that an eect app ears on the right of the turnstile but not on the left This

is b ecause we are only considering CBV languages and that means that at

runtime free variables will always b e b ound to values which have no eect An

eect system for an impure CBN language were there any such thing would

have pairs of typ es and eects in the context to o Because variables are always

b ound to values the asso ciated typ e and eect rule will b e

x A x A

The second p oint is that E actually needs to b e an algebra rather than

just a set ie it has some op erations for combining eects dened on it Con

sider the eectful version of the rule for a simple strict nonp olymorphic non

computational let expression

M A x A N B

let x M in N B

What should the eect of the comp ound expression b e Dynamically M will b e

evaluated p ossibly p erforming some sideeect from the set denoted by and

assuming the evaluation of M terminated with a value V then N V x will b e

evaluated and p ossibly p erform some sideeect from the set denoted by How

we combine and dep ends on how much accuracy we are willing to pay for

in our static analysis If we care ab out the relative ordering of sideeects then

we might take elements of E to denote sets of sequences eg regular languages

over some basic set of eects and then use language concatenation to

combine the eects in the let rule Commonly however we abstract away from

the relative sequencing and multiplicity of eects and just consider sets of basic

eects In this case the natural combining op eration for the let rule is some

abstract union op eration

For the conditional expression the following is a natural rule

M b o ol N A N A

if M then N else N A

If we were not tracking sequencing or multiplicity then the eect in the conclu

sion of the if rule would just b e of course

Although the mixture of CBN and sideeects is an unpredictable one Haskell do es

actually allow it via the exp ertsonly unsafePerformIO op eration But Im still

not aware of any typ e and eect system for a CBN language

Eect systems in the literature often include a binary op eration in the formal

syntax of eect annotations which are then considered mo dulo unit asso ciativity

commutativity and idemp otence For very simple eect systems this is unnecessar

ily syntactic but its not so easy to avoid when one also has eect variables and substitution

The other main interesting feature of almost all typ e and eect systems is the

form of the rules for abstraction and application which make typ es dep endent

on eects in that the function space constructor is now annotated with a latent

eect A B The rule for abstraction lo oks like

x A M B

x A M A B

b ecause the abstraction itself is a value and so has no immediate eect but

will have eect when it is applied as can b e seen in the rule for application

1

B N A M A

M N B

The overall eect of evaluating the application is made up of three separate

eects that which o ccurs when the function is evaluated that which o ccurs

when the argument is evaluated and nally that which o ccurs when the b o dy

of the function is evaluated Again most eect systems work with sets rather

than sequences so the combining op eration in the conclusion of the application

rule is just

The nal thing we need to add to our minimal skeleton eect system is some

way to weaken eects The collection E of eects for a given analysis always has

a natural partial order relation dened on it such that means denotes

a larger set of p ossible runtime sideeects than Typically is just the

relation on sets of primitive eects The simplest rule we can add to make a

usable system is the subeecting rule

M A

M A

Exercise Dene a toy simplytyp ed CBV functional language integers b o oleans

pairs functions with a xed collection of global mutable integer vari

ables Give it an op erational andor denotational semantics Give a typ e and

eect system with sub eecting for your language which tracks which global

variables may b e read and written during the evaluation of each expression so

an eect will b e a pair of sets of global variable names Formulate and prove a

soundness result for your analysis Are there any closed terms in your language

which require the use of the sub eect rule to b e typable at all

More Precise Eect Systems

One of the great things ab out static analyses is that one can always tweak any

analysis system to make it more accurate There are a numb er of natural

and p opular ways to improve the precision of the hop elessly weak simpletyp es

approach to eect analysis sketched in the previous section

This corollary to the unsolvability of the Halting Problem is known as The Full

Employment for Compiler Writers

Subtyping The bidirectional ow of information in typ e systems or analyses

which simply constrain typ es to b e equal frequently leads to an undesirable loss

of precision For example consider an eect analysis of the following very silly

ML program and forget p olymorphism for the moment

let fun f x

fun pure

fun impure print Im a sideeffect

val m f pure f impure

in pure

end

If they were typ ed in isolation the b est typ e for pure would b e unit unit

fprintg

and impure would get unit unit assuming that the constant print has

fpr intg

typ e string unit However the fact that b oth of them get passed to the

function f means that we end up having to make their typ es including the latent

eects identical This we can do by applying the sub eecting rule to the b o dy

fprintg

of pure and hence deriving the same typ e unit unit for b oth pure and

impure But then that ends up b eing the typ e inferred for the whole expression

when its blindingly obvious that we should have b een able to deduce the more

accurate typ e unit unit

The fact that the argument typ e of f has to b e an impure function typ e has

prop ogated all the way back to the denition of pure Peyton Jones has given

this phenomenon the rather apt name of the poisoning problem One solution is

to extend to notion of sub eecting to allow more general subtyping We replace

the sub eecting rule with

M A A A

M A

where is a partial order on typ es dened by rules like

A A B B

A A B B

and

0

A B A B

B A B A

Note the contravariance of the function space constructor in the argument typ e

Using the subtyping rule we can now get the typ e and eect wed exp ect for

our silly example The denitions of pure and impure are given dierent typ es

but we can apply the subtyping rule writing for unit

fprintg

fprintg

pure pure

fprintg

pure pure

to co erce the use of pure when it is passed to f to match the required argument

typ e whilst still using the more accurate typ e inferred at the p oint of denition

as the typ e of the whole expression

Eect Polymorphism Another approach to the p oisoning problem is to intro

duce MLstyle p olymorphism at the level of eects this is largely orthogonal to

whether we also have p olymorphism at the level of typ es We allow eects to

contain eect variables and then to allow the context to bind identiers to typ e

schemes which quantify over eect variables

Consider the following program

let fun run f f

fun pure

fun impure print Poison

fun h run impure

in run pure

end

In this case even with subtyping we end up deriving a typ e and eect of

unit fprintg for the whole program though it actually has no side eect With

eect p olymorphism we can express the fact that there is a dep endency b etween

the eect of a particular call to run and the latent eect of the function which

is passed at that p oint The denition of run gets the typ e scheme

a a

aunit unit unit

which is instantiated with a in the application to pure and a fprintg

in the application to impure which is actually never executed That lets us

deduce a typ e and eect of unit for the whole program

Regions One of the most inuential ideas to have come out of work on typ e

and eect systems is that of regions static abstractions for sets of dynamically

allo cated runtime lo cations If as in the earlier exercise one is designing an

eect system to track the use of mutable storage in a language with a xed set

of global lo cations there are two obvious choices for how precisely one tracks

the eects either one records simply whether or not an expression might read

or write some unsp ecied lo cations or one records a set of just which lo cations

might b e read or written Clearly the second is more precise and can b e used

to enable more transformations For example the evaluation of an expression

whose only eect is to read some lo cations might b e moved from after to b efore

the evaluation of an expression whose eect is to write some lo cations if the set

of lo cations p ossibly read is disjoint from the set of lo cations p ossibly written

But no real programming language with the p ossible exception of ones de

signed to b e compiled to silicon allows only a statically xed set of mutable

lo cations When an unb ounded numb er of new references may b e allo cated dy

namically at runtime a static eect system clearly cannot name them all in

advance The simple approach of just having one big abstraction for all lo ca

tions the store and tracking only whether some reading or some writing takes

place is still sound but we would like to b e more precise

In many languages the existing typ e system gives a natural way to partition

the runtime set of mutable lo cations into disjoint sets In an MLlike language an

int ref and a bool ref are never aliased so one may obtain a useful increase

in precision by indexing read write and allo cation eects by typ es Ignoring

p olymorphism again we might take

E PfrdA wrA al A j A a typ eg

Note that typ es and eects are now mutually recursive

But we can do even b etter Imagine that our language had two quite distinct

typ es of references say red ones and blue ones and one always had to say

which sort one was creating or accessing Then clearly a red reference and a blue

reference can never alias we could rene our eect typ es system to track the

colours of references involved in store eects and we could p erform some more

transformations for example commuting an expression which can only write

blue integer references with one which only reads red integer references

In its simplest form the idea of region inference is to take a typing derivation

for a mono chrome program and to nd a way of colouring each reference typ e

app earing in the derivation sub ject to preserving the of the derivation

so for example a function exp ecting a red reference as an argument can never b e

applied to a blue one It should b e clear that the aim is to use as many dierent

colours as p ossible The colours are conventionally called regions b ecause one

can imagine that dynamically all the lo cations of a given colour are allo cated in

a particular region of the heap

So now we have three static concepts typ e eect and region Each of these

can b e treated monomorphically with a subwidget relation or p olymorphically

The typ e and eect discipline describ ed by Talpin and Jouvelot in TJ is

p olymorphic in all three comp onents and indexes reference eects by b oth regions

and typ es

Perhaps the most interesting thing ab out regions is that we can use them to

extend our inference system with a rule in which the eect of the conclusion is

smal ler than the eect of the assumption Consider the following example

fun f x let val r ref x

in r

end

Alternatively one might think that any runtime lo cation will have a unique allo cation

site in the co de and all lo cations with the same allo cation site will share a colour

so one could think of a region as a set of static program p oints But this is a less

satisfactory view since more sophisticated systems allow references allo cated at the

same program p oint to b e in dierent regions dep ending on more dynamic contextual

information such as which functions app ear in the call chain

falr dg

A simple eect system would assign f a typ e and eect like int int

which seems reasonable since it is indeed a functional value which takes integers

to integers with a latent eect of allo cating and reading But the fact that f

has this latent eect is actually completely unobservable since the only uses of

storage it makes are completely private In this case it is easy to see that f is

observationally equivalent to the completely pure successor function

fun f x x

which means that provided the use to which we are going to make of eect

information resp ects observational equivalence we could soundly just forget all

ab out the latent eect of f and infer the typ e int int for it instead How do

regions help A simple typ e region and eect derivation lo oks like this

xint xint

xint rint ref

rint frd g

xint ref xint ref fal g

xint let rref x in rint fal rd g

fal rd g

fn xlet rref x in r int int

where is a region Now this is a valid derivation for any choice of in particular

we can pick to b e distinct from any region app earing in That means that the

b o dy of the function do es not have any eect involving references imp orted from

its surrounding context Furthermore the typ e of the function b o dy is simply

int so whatever the rest of the program do es with the result of a call to the

function it cannot have any dep endency on the references used to pro duce it

Such considerations motivate the eect masking rule

M A

M A n frd al wr j Ag

Using this rule b efore just b efore typing the abstraction in the derivation ab ove

do es indeed allow us to typ e f as having no observable latent eect

One of the most remarkable uses of region analysis is Tofte and Talpins

work on static memory management TT they assign regionannotated typ es

to every nonbase value rather than just mutable references in an intermedi

ate language where new lexicallyscop ed regions are intro duced explicitly by a

letregion in end construct For a welltyp ed and annotated program in

this language no value allo cated in region will b e referenced again after the

end of the letregion blo ck intro ducing Hence that region of the heap may

This should b e the case for justifying optimising transformations or inferring more

generous p olymorphic typ es but might not b e in the case of a static analysis to ol

which helps the programmer reason ab out say memory usage

b e safely reclaimed on exiting the blo ck This technique has b een successfully

applied in a version of the ML Kit compiler in which there is no runtime garbage

collector at all For some programs this scheme leads to dramatic reductions in

runtime space usage compared with traditional garbage collection whereas for

others the results are much worse Combining the two techniques is p ossible but

requires some care since the regionbased memory management reclaims mem

ory which will not b e referenced again but to which there may still b e p ointers

accessible from the GC ro ot The GC therefore needs to avoid following these

dangling p ointers

The soundness of eect masking in the presence of highertyp e references

and of regionbased memory management is not at all trivial to prove Both

TJ and TT formulate correctness in terms of a coinductively dened con

sistency relation b etween stores and typing judgements A numb er of researchers

have recently published more elementary pro ofs of the correctness of region cal

culi either by translation into other systems BHRdZG or by more direct

metho ds HTCal

Monads and Eect Systems

Intro duction

This section describ es how typ e and eect analyses can b e presented in terms of

monads and the computational metalanguage Although this is actually rather

obvious it was only recently that anyb o dy got around to writing anything seri

ous ab out it In ICFP Wadler published a pap er Wad later extended

and corrected as WT showing the equivalence of a mild variant of the eect

system of Talpin and Jouvelot TJ and a version of the computational met

alanguage in which the computation typ e constructor is indexed by eects In

the same conference Benton Kennedy and Russell describ ed the MLj compiler

BKR and its intermediate language MIL which is a similar eectrened

version of the computational metalanguage Also in Tolmach prop osed an

intermediate representation with a hierarchy of monadic typ es for use in com

piling ML by transformation Tol

The basic observation is that the places where the computation typ e construc

tor app ears in the callbyvalue translation of the lamb da calculus into ML

T

corresp ond precisely to the places where eect annotations app ear in typ e and

eect systems Eect systems put an over each function arrow and on the

righthand side of turnstiles whilst the CBV translation adds a T to the end of

each function arrow and on the right hand side of turnstiles Wadler started with

a CBV lamb da calculus with a valuep olymorphic typ e region and eect system

tracking store eects without eect masking He then showed that Moggis

CBV translation of this language into a version of the metalanguage in which

the computation typ e constructor is annotated with a set of eects and the

monadic let rule unions these sets preserves typing in that

v v v

M A M T A

ef f mon

where

v

int int

v v v

A B A T B

Wadler also dened an instrumented op erational semantics for each of the two

languages and used these to prove sub ject reduction typ e soundness results in the

style of Wright and Felleisen WF The instrumented op erational semantics

records not only the evaluation of an expression and a state to a value and a

new state but also a trace of the side eects which o ccur during the evaluation

part of the denition of typ e soundness is then that when an expression has a

static eect any eect o ccuring in the dynamic trace of its evaluation must b e

contained in

Tolmachs intermediate language has four monads

The identity monad used for pure terminating computations

The lifting monad used to mo del p otential nontermination

The monad of exceptions and nontermination

The ST monad which combines lifting exceptions and the p ossibility of

p erforming output

These are linearly ordered with explicit monad morphisms used to co erce com

putations from one monad typ e to a larger one Tolmach gives a denotational

semantics for his intermediate language using cp os and presents a numb er of

useful transformation laws which can b e validated using this semantics

MILlite Monads in MLj

MILlite is a simplied fragment of MIL the intermediate language used in the

MLj compiler It was intro duced by Benton and Kennedy in BK as a basis

for proving the soundness of some of the eectbased optimizing transforma

tions p erformed by MLj Compared with many eect systems in the literature

MIL only p erforms a fairly crude eect analysis it do esnt have regions ef

fect p olymorphism or masking MILlite further simplies the full language by

omitting typ e p olymorphism highertyp e references and recursive typ es as well

as various lower level features Nevertheless MILlite is far from trivial com

bining higherorder functions recursion exceptions and dynamically allo cated

state with eectindexed computation typ es and subtyping

Typ es and terms MILlite is a compiler intermediate language for which we

rst give an op erational semantics and then derive an equational theory so there

are a couple of design dierences b etween it and Moggis equational metalan

guage The rst is that typ es are stratied into value typ es ranged over by

and computation typ es ranged over by we will have no need of computations

of computations The second dierence is that the distinction b etween compu

tations and values is alarmingly syntactic the only expressions of value typ es

are normal forms It is p erhaps more elegant to assign value typ es to a wider

collection of pure expressions than just those in normal form That is the way

Wadlers eectannotated monadic language is presented and it leads naturally

to a stratied op erational semantics in which there is one relation dening the

pure reduction of expressions of value typ e to normal form and another dening

the p ossibly sideeecting evaluation of computations

Given a E of exception names MILlite typ es are dened by

unit j int j intref j j j

T E f r w ag E

We write b o ol for unit unit Function typ es are restricted to b e from values

to computations as this is all we shall need to interpret a CBV source language

The eects which we detect are p ossible failure to terminate r eading from

a reference w riting to a reference a llo cating a new reference cell and raising

a particular exception E E Inclusion on sets of eects induces a subtyping

relation

6

funit int intrefg

6

0

T 6 T

6 6 6 6

6 6

6 6

6

Reexivity and transitivity are consequences of these rules

There are two forms of typing judgment V for values and M

for computations where in b oth cases is a nite map from term variables to

value typ es b ecause the source language is CBV We assume a countable set

L of lo cations The typing rules are shown in Figure and satisfy the usual

weakening strengthening and substitution lemmas We will sometimes use G to

range over b oth value and computation terms and to range over b oth value

and computation typ es Most of the terms are unsurprising but we do use a

novel construct

try x M catch fE M E M g in N

n n

which should b e read Evaluate the expression M If successful bind the result

to x and evaluate N Otherwise if exception E is raised evaluate the exception

i

handler M instead or if no handler is applicable pass the exception on A full

i

discussion of the reasons for adopting the tryhandle construct may b e found in

BK but for now observe that it nicely generalises b oth handle and Moggis

monadic let as illustrated by some of the syntactic sugar dened in Figure

For ease of presentation the handlers are treated as a set in which no ex

ception E app ears more than once We let H range over such sets and write

H n E to denote H with the handler for E removed if it exists We sometimes

use maplike notation for example writing H E for the term M in a handler

E M H and writing domH for fE j E M H g We write H to

mean that for all E M H M

L

unit

n int intref

x x

V V

V

i

i

V V

in V

i

V

x f T M T

fg

6

V

rec f x M T

V

V V

val V T

V V

0 0

x N T M T H T

raise E T

fE g

0

try x M catch H in N T

ndomH

V

V f x M g

i i i

i

i

V T

case V of in x M in x M

i i

V int V intref V intref V int

ref V T intref V T int V V T unit

fag fr g fw g

V int V int V int V int

M

6

V V T int V V T b o ol

M

Fig Typing rules for MILlite

def

x M rec f x M f FV M

def

rec f x f x

def

false in

def

true in

def

if V then M else M case V of in x M in x M x FV M

i i

def

let x M in N try x M catch fg in N

def

let x M x M in N let x M in let x M in N

def

M N let x M in N x FV N

def

try x M catch H in val x M handle H

def

n n val set f n n g

k k k k

def

b v n in if b then val else assert n let v

def

assert f n n g assert n assert n val

k k k k

Fig Syntactic sugar

The analysis The way in which the MILlite typing rules express a simple

eects analysis should b e fairly clear though some features may deserve fur

ther comment The intro duction rule incorp orates an extremely feeble but

nonetheless very useful termination test the more obvious rule would insist that

but that would prevent xM from getting the natural derived typing rule

and would cause undesirable nontermination eects to app ear in particularly

curried recursive functions

Just as with traditional eect systems the use of subtyping increases the

accuracy of the analysis compared with one which just uses simple typ es or

sub eecting

There are many p ossible variants of the rules For example there is a stronger

try rule in which the eects of the handlers are not all required to b e the same

and only the eects of handlers corresp onding to exceptions o ccurring in are

unioned into the eect of the whole expression

Exercise Give examples which validate the claim that the intro duction

rule gives b etter results than the obvious version with

MILlite do es not include recursive typ es or highertyp e references b ecause

they would make proving correctness signicantly more dicult But can you de

vise candidate rules for an extended language which do es include these features

Theyre not entirely obvious esp ecially if one tries to make the rules reasonably

precise to o It may help to consider

datatype U L of UU

and

let val r ref fn

val r fn r

in r

end

Op erational semantics We present the op erational semantics of MILlite us

ing a bigstep evaluation relation M R where R ranges over value terms

def

and exception identiers and States L Z

n

Write M if M R for some R and bGc for the set of lo cation

names o ccuring in G If States then States is dened by

if thats dened and otherwise

In BK we next prove a numb er of technical results ab out the op erational

semantics using essentially the techniques describ ed by Pitts in his lectures

Pita Since most of that material is not directly related to monads or eects

we will omit it from this account but the imp ortant p oints are the following

We are interested in reasoning ab out contextual equivalence which is a type

indexed relation b etween terms in context

G G ctx

val V V raise E E V V V

i i

m n m n n true n m false n m n

n n ref n n

M V x R

i i

i

case in V of in x M in x M R

i

M V x rec f x M f R

M V N V x R

rec f x M V R

try x M catch H in N R

M E M R

H E M

try x M catch H in N R

M E

E domH

try x M catch H in N E

Fig Evaluation relation for MILlite

Rather than work with contextual equivalence directly we show that contex

tual equivalence coincides with ciu equivalence which shows that only certain

sp ecial contexts need b e considered to establish equivalence For MILlite

ciu equivalence is the op en extension of the relation dened by the following

clauses

If M T and M T we write M M T and say M is

ciu equivalent to M at type T when N H such that x N

and H and States such that dom bM M H N c we

have

try x M catch H in N try x M catch H in N

If V and V then we write V V for val V val V T

Transforming MILlite

Semantics of Eects We want to use the eect information expressed in MIL

lite typ es to justify some optimizing transformations Our initial inclination was

to prove the correctness of these transformations by using a denotational seman

tics However giving a go o d denotational semantics of MILlite is surprisingly

tricky not really b ecause of the multiple computational typ es but b ecause of

the presence of dynamically allo cated references Starks thesis Sta examines

equivalence in a very minimal language with dynamically generated names in

considerable detail and do es give a functor category semantics for a language

with higher order functions and integer references But MILlite is rather more

complex than Starks language requiring a functor category into cp os rather

than sets and then indexed monads over that Worst of all the resulting se

mantics turns out to b e very far from fully abstract it actually fails to validate

some of the most elementary transformations which we wished to p erform So we

decided to prove correctness of our transformations using op erational techniques

instead

Most work on using op erational semantics to prove soundness of eect anal

yses involves instrumenting the semantics to trace computational eects in some

way and then proving that welltyp ed programs dont go wrong in this mo di

ed semantics This approach is p erfectly correct but the notion of correctness

and the meaning of eect annotations is quite intensional and closely tied to

the formal system used to infer them Since we wanted to prove the soundness

of using the analysis to justify observational equivalences in an uninstrumented

semantics we instead tried to characterise the meaning of eectannotated typ es

as prop erties of terms which are closed under observational equivalence in the

uninstrumented semantics To give a simple example of the dierence b etween

the two approaches a weak eect system such as that in MILlite will only

assign a term an eect which do es not contain w if the evaluation of that term

really do es never p erform a write op eration A regionbased analysis may infer

such an eect if it can detect that the term only writes to private lo cations But

the prop erty we real ly want to use to justify equations is much more extensional

its that after evaluating the term the contents of all the lo cations which were

allo cated b efore the evaluation are indistinguishable from what they were to

start with

The decision not to use an instrumented semantics is largely one of taste

but there is another p ost ho c justication There are a few places in the MLj

libraries where we manually annotate bindings with smaller eect typ es than

could b e inferred by our analysis typically so that the rewrites can deadco de

them if they are not used for example the initialisation of lo okup tables used

in the oating p oint libraries Since those bindings do have the extensional

prop erties asso ciated with the typ e we force them to have the correctness result

for our optimizations extends easily to these manually annotated expressions

We capture the intended meaning of each typ e in MILlite as the set

of closed terms of that typ e which pass all of a collection of cotermination tests

Tests States Ctxt Ctxt where Ctxt is the set of closed contexts with

a nite numb er of holes of typ e Formally

def

f G j M M Tests

bM G M Gc dom M G M G g

We dene Tests inductively as shown in Figure

def def def

Tests fg Tests fg Tests fg

int unit

intref

S

def

Tests g f M M j M M Tests

i i

1 2

i

i

S

def

f case of in xM x in y Tests

i i

1 2

i

g case of in xM x in y j M M Tests

i i

i

def

Tests f M V M V j V M M Tests g

def

Tests f let x in set M x let x in set M x

T

S

j M M Tests Statesg Tests

e

e

where

def

Tests f val j Statesg

def

f let y in try x catch E M in N Tests

w

try x catch E let y in M in let y in N

j y int x N y int M States dom g

def

f d E try x catch E assert raise E in N Tests

r

d E n try x catch E assert n raise E

N in assert n

j E E States dom dom n Z x N g

f handle E set handle E j States E E g

def

Tests f handle E N j States N g

E

def

Tests f let x y set in N let x y val x in N

a

j States x y N g

and

def

K n f n j dom g

def

d E set K val handle E val assert K

set K val handle E val assert K set

Fig Denition of Tests

Although these denitions app ear rather complex at value typ es they actu

ally amount to a familiarlo oking logical predicate

Lemma

int fn j n Zg intref f j L g and unit fg

fV V j V V g

fF j V F V g

S

fin V j V g

i i

i

ut

Lemma If 6 then ut

We also have to prove an op erational version of admissibility for the predicate

asso ciated with each typ e This follows from a standard compactness of evalua

tion or unwinding result which is proved using termination induction but we

omit the details Finally we can prove the Fundamental Theorem for our logical

predicate which says that the analysis is correct in the sense that whenever a

term is given a particular typ e it actually satises the prop erty asso ciated with

that typ e

Theorem If x G and V then GV x ut

i i i i i i

Although we have explained the meaning of the logical predicate at value

typ es it seems worth commenting a little further on the denitions of Tests

e

The intention is that the extent of Tests is the set of computations of typ e

e

T which denitely do not have eect e So passing all the tests in Tests

E

is easily seen to b e equivalent to not diverging in any state and passing all the

tests in Tests means not throwing exception E in any state

E

The tests concerning store eects are a little more subtle It is not to o hard to

see that Tests expresses not observably writing the store Similarly Tests

w r

tests contortedly for not observably reading the store by running the compu

tation in dierent initial states and seeing if the results can b e distinguished by

a subsequent continuation

the extent of The most surprising denition is probably that of Tests

a

which is intended to b e those computations which do not observably allo cate

any new storage lo cations This should include for example a computation

which allo cates a reference and then returns a function which uses that reference

to keep count of how many times it has b een called but which never reveals

the counter nor returns dierent results according to its value However the

do es not seem to say anything ab out store extension what denition of Tests

a

it actually captures is those computations for which two evaluations in equivalent

initial states yield indistinguishable results Our choice of this as the meaning of

do esnt allo cate was guided by the optimising transformations which we wished

to b e able to p erform rather than a deep understanding of exactly what it means

to not allo cate observably but in retrosp ect it seems quite reasonable

V x M V V

T

V V let x val V in M val V T M V x

i i i

x f T M T V

fg

rec f x M V M V x rec f x M f T

V x M x M

i

M V x case in V of in x M in x M

i i i

V

let x V x V in val x x val V T

V

case V of in x val in x in x val in x val V T

M V

T

rec f x V x let x M in val x V M

y x M T y M T M T

3 2 1

cc

let x let y M in M in M let y M x M in M T

1 2 3

0

V f x M T g x N T

i i i

cc

0

let x case V of fin x M g in N case V of fin x let x M in N g T

i i i i i i

M H x N

E

try x raise E catch E M H in N M

0 0

x N T M T H T

E

0

try x M catch E raise E H in N try x M catch H in N T

Fig Eectindep endent equivalences

Eectindep endent equivalences Figure presents some typ ed observational

congruences that corresp ond to identities from the equational theory of the com

putational lamb da calculus and Figure presents equivalences that involve

lo cal sideeecting b ehaviour Directed variants of many of these are useful

transformations that are in fact p erformed by MLj although the duplication

of terms in cc is avoided by intro ducing a sp ecial kind of abstraction These

equations can b e derived without recourse to our logical predicate by making

use of a rather strong notion of equivalence called Kleene equivalence that can

easily b e shown to b e contained in ciu equivalence Two terms are Kleene equiv

alent if they coterminate in any initial state with syntactically identical results

and the same values in all accessible lo cations of the store Mason and Talcott

call this strong isomorphism MT

V int M T

let x ref V in M M T

fag

V intref x int y int M T

let x V y V in M let x V y val x in M T

fr g

V int V int x intref x intref M T

let x ref V x ref V in M let x ref V x ref V in M T

fag

V intref V int x int M T

V V let x V in M V V M V x T

frw g

Fig Eectindep endent equivalences

The b etaequivalences and commuting conversions of Figure together with

the equivalences of Figure are derived directly as Kleene equivalences Deriva

tion of the etaequivalences involves rst deriving a numb er of

prop erties using ciu equivalence similar techniques are used in Pit

Eectdep endent equivalences We now come to a set of equivalences that

are dep endent on eect information which are shown in Figure Notice how

the rst three of these equations resp ectively subsume the rst three lo cal equiv

alences of Figure Each of these equivalences is proved by considering evalua

tion of each side in an arbitrary ciucontext and then using the logical predicate

to show that if the evaluation terminates then so do es the evaluation of the other

side in the same context

Some side conditions on variables are implicit in our use of contexts For example

the rst equation in Figure has the side condition that x f v M

N T M T

2 1

discard

let x M in N N T

1 2

where fr ag

0

M T x y N T

copy

0

let x M y M in N let x M y val x in N T

where fr ag or fw ag

x x N T M T M T

3 2 1

swap

let x M x M in N let x M x M in N T

1 2 3

where fr a g or fa g fr w a g

0 0

x N T M T H T

deadtry

0

try x M catch H in N try x M catch H n E in N T

where E

Fig Eectdep endent equivalences

EectDep endent Rewriting in MLj

In practice much of the b enet MLj gets from eectbased rewriting is simply

from deadco de elimination discard and deadtry A lot of dead co de particu

larly straight after linking is just unused toplevel function bindings and these

could clearly b e removed by a simple syntactic check instead of a typ ebased

eect analysis Nevertheless b oth unused nonvalues which detectably at most

read or allo cate and unreachable exception handlers do o ccur fairly often to o

and it is convenient to b e able to use a single framework to eliminate them

all Here is an example from BK of how tracking exception eects works

together with MILs unusual handler construct to improve an ML program for

summing the elements of an array

fun sumarray a

let fun snsofar let val v Arraysuban

in sn sofarv

end handle Subscript sofar

in s

end

Because the SML source language do esnt have try the programmer has made

the handler cover b oth the array access and the recursive call to the inner func

tion s But this would prevent a nave compiler from recognising that call as

tailrecursive In MLj the intermediate co de for s lo oks like in MLish rather

than MIL syntax

fun snsofar

try val x try val v Arraysuban

catch

in sn sofarv

end

catch Subscript sofar

in x

end

A commuting conversion turns this into

fun snsofar try val v Arraysuban

catch Subscript sofar

in try val x sn sofarv

catch Subscript sofar

in x

end

end

The eect analysis detects that the recursive call to s cannot in fact ever throw

the Subscript exception so the function is rewritten again to

fun snsofar try val v Arraysuban

catch Subscript sofar

in sn sofarv

end

which is tail recursive and so gets compiled as a lo op in the nal co de for

sumarray

Making practical use of the swap and copy equations is more dicult al

though it is easy to come up with real programs which could b e usefully improved

by sequences of rewrites including those equations it is hard for the compiler to

sp ot when commuting two computations makes useful progress towards a more

signicant rewrite The most signicant eectbased co de motion transformation

which we do p erform is pulling constant pure computations out of functions in

particular lo ops a sp ecial case of which is

M T f T x y N T

val rec f x let y M in N let y M in val rec f x N T T

where theres an implied side condition that neither f nor x is free in M This is

not always an improvement if the function is never applied but in the absence

of more information its worth doing anyway Slightly embarassingly this is not

an equivalence which we have proved correct using the techniques describ ed here

however

One other place where information ab out which expressions commute could

usefully b e applied is in a compiler backend for example in register allo cation

We havent tried this in MLj since a JIT compiler will do its own job of al

lo cating real machine registers and scheduling real machine instructions later

which makes doing a very go o d job of compiling virtual machine co de unlikely

to pro duce great improvements in the p erformance of the nal machine co de

An early version of the compiler also implemented a typ edirected uncurrying

transformation exploiting the isomorphism

T T T

but this can lead to extra work b eing done if the function is actually partially

applied so this transformation also seems to call for auxiliary information to b e

gathered

Eect Masking and Monadic Encapsulation

We have seen that it is not to o hard to recast simple eect systems in a monadic

framework But what is the monadic equivalent of eect masking The answer

is something like the encapsulation of sideeects provided by runST in Haskell

but the full connection has not yet b een established

Haskell allows monadic computations which make purely lo cal use of state

to b e encapsulated as values with pure typ es by making use of a cunning trick

with typ e variables which is very similar to the use of regions in eect systems

Briey see Section for more information the state monad is parameterized

not only by the typ e of the state s but also by another dummy typ e variable

r In MLish syntax

datatype rsa ST S of s s a

The idea is that the r parameters of typ es inferred for computations whose states

might interfere will b e unied so if a computation can b e assigned a typ e which is

parametrically p olymorphic in r then its use of state can b e encapsulated This

is expressed using the runST combinator which is given the rank p olymorphic

typ e

runST s arr s aST a

Just as the soundness of eect masking and of the region calculus is hard to

establish proving the correctness of monadic encapsulation is dicult Early

attempts to prove soundness by sub ject reduction LS are now known to b e

incorrect

More recently Semmelroth and Sabry have succeeded in dening a CBV lan

guage with monadic encapsulation relating this to a language with eect mask

ing and proving typ e soundness SS Moggi and Palumb o have also addressed

this problem MP by dening a slightly dierent form of monadic encapsula

tion without the b ogus typ e parameter and proving a typ e soundness result

for a language in which the stateful op erations are strict Proving soundness for

monadic encapsulation in a CBN language with lazy state op erations is still so

far as I am aware an op en problem

Actually Haskells builtin state monad is not parameterized on the typ e of the state itself

CurryHoward Corresp ondence and Monads

This section provides a little optional background on a logical reading of the

computational metalanguage and explains the term commuting conversion

Most readers will have some familiarity with the socalled CurryHoward

Corresp ondence or Isomorphism aka the Prop ositionsasTyp es Analogy This

relates typ es in certain typ ed lamb da calculi to prop ositions in intuitionistic

typ ed terms in context to pro ofs of prop ositions from

assumptions and reduction to pro of normalization The basic example of the

corresp ondence relates the simply typ ed lamb da calculus with function pair

and disjoint union typ es to intutionisitic prop ositional logic with implication

and disjunction GLT

Whilst it may b e true that almost no realistic programming language corre

sp onds accurately to anything which might plausibly b e called a logic b ecause of

the presence of general recursion if nothing else logic and pro of theory can still

provide helpful insights into the design of programming languages and interme

diate languages Partly this seems to b e b ecause pro of theorists have develop ed

a numb er of taxonomies and criteria for wellb ehavedness of pro of rules which

turn out to b e transferable to the design of go o d language syntax

The computational metalanguage provides a nice example of the applicability

of pro of theoretic ideas see BBdP for details If one reads the typ e rules for

the intro duction and elimination of the computation typ e constructor logically

then one ends up with an intuitionistic modal logic which we dubb ed CLlogic

with a slightly unusual kind of p ossibility mo dality In sequentstyle natural

deduction form

A A A B

I E

A B

Interestingly not only was the Hilb ertstyle presentation of this logic discov

ered by Fairtlough and Mendler who call it lax logic in the context of hard

ware verication FM but it had even b een considered by Curry in

Cur Moreover from a logical p ersp ective the three basic equations of the

computational metalanguage arise as inevitable consequences of the form of the

intro duction and elimination rules rather than b eing imp osed separately

The way in which the rule for the computation typ e constructor arises

from the natural deduction presentation of the logic is fairly straightforward the

basic step in normalization is the removal of detours caused by the intro duction

and immediate elimination of a logical connective

A A

A

A A

I

A B

E

B

B

M A

N M x TB

val M TA x A N TB

let x val M in N TB

Natural deduction systems can also give rise to a secondary form of normal

isation step which are necessary to ensure that normal deductions satisfy the

subformula prop erty for example These o ccur when the system contains elimi

nation rules which have a minor premiss Girard calls this a parasitic formula

and refers to the necessity for these extra reduction the shame of natural de

duction GLT In general when we have such a rule we want to b e able

to commute the last rule in the derivation of the minor premiss down past the

rule or to move the application of a rule to the conclusion of the elimination

up past the elimination rule into to the derivation of the minor premiss The

only imp ortant cases are moving eliminations up or intro ductions down Such

transformations are called commuting conversions The elimination rule for dis

junction copro ducts in intuitionisitic logic gives rise to commuting conversions

and so do es the elimination for the mo dality of CLlogic The restriction on

the form of the conclusion of our rule it must b e mo dal means that the

E

rule gives rise to only one commuting conversion

A deduction of the form

A

B

A B

E

B C

E

C

commutes to

A B

B C

E

A C

E

C

On terms of the computational metalanguage this commuting conversion in

duces the let of a let asso ciativity rule

M TA y A P TB

let y M in P TB x B N TC

let x let y M in P in N TC

y A P TB y A x B N TC

M TA y A let x P in N TC

let y M in let x P in N TC

Commuting conversions are not generally optimizing tranformations in their

own right but they reorganise co de so as to exp ose more computationally sig

nicant reductions They are therefore imp ortant in compilation and most

compilers for functional languages p erform at least some of them MLj is some

what dogmatic in p erforming al l of them to reach what we call ccnormal form

from which it also turns out to b e particularly straighforward to generate co de

As Danvy and Hatcli observe HD this is closely related to working with

Anormal forms though the logicalpro of theoretic notion is an older and more

precisely dened pattern

Acknowledgements

We have used Paul Taylors package for diagrams

References

App A W App el Compiling with Continuations Cambridge University

Press

BBdP P N Benton G M Bierman and V C V de Paiva Computational

typ es from a logical p ersp ective Journal of Functional Programming

March Preliminary version app eared as Technical

Rep ort University of Cambridge Computer Lab oratory May

Ben P N Benton Strictness Analysis of Lazy Functional Programs PhD

thesis Computer Lab oratory University of Cambridge Decemb er

BHR A Banerjee N Heintze and J G Reicke Region analysis and the

p olymorphic lamb da calculus In Fourteenth IEEE Symposium on Logic

and Computer Science

BHT G Barthe J Hatcli and P Thiemann Monadic typ e systems Pure

typ e systems for impure settings In Proceedings of the Second HOOTS

Workshop Stanford University Palo Alto CA December Elec

tronic Notes in Theoretical Computer Science Elsevier February

BK N Benton and A Kennedy Monads eects and transformations In

Third International Workshop on Higher Order Operational Techniques

in Semantics HOOTS Paris volume of Electronic Notes in Theo

retical Computer Science Elsevier Septemb er

BK N Benton and A Kennedy Exceptional syntax Journal of Functional

Programming To app ear

BKR N Benton A Kennedy and G Russell Compiling Standard ML to

Java byteco des In rd ACM SIGPLAN Conference on Functional Pro

gramming Septemb er

BM G L Burn and D Le Metayer Proving the correctness of compiler

optimisations based on a global program analysis Technical Rep ort

Do c Department of Computing Imp erial College London

BNTW P Buneman S Naqvi V Tannen and L Wong Principles of program

ming with complex ob jects and collection typ es Theoretical Computer

Science

Bor F Borceux Handbook of Categorial Algebra Cambridge University

Press

BS Erik Barendsen and Sjaak Smetsers Uniqueness typing for functional

languages with graph rewriting semantics Mathematical Structures in

Computer Science pages

Bur W Burge Recursive Programming Techniques AddisonWesley Pub

lishing Company Reading Mass

BW M Barr and C Wells Toposes Triples and Theories Springer

Cal C Calcagno Stratied op erational semantics for safety and correctness

of the region calculus In th ACM SIGPLANSIGACT Symposium on

Principles of Programming Languages January

CM P Cenciarelli and E Moggi A syntactic approach to mo dularity in

denotational semantics In CTCS CWI Tech Rep ort

Cur H B Curry The elimination theorem when mo dality is present Journal

of Symbolic Logic January

DH O Danvy and J Hatcli CPS transformation after strictness analysis

ACM Letters on Programming Languages and Systems

dZG S dal Zilio and A Gordon Region analysis and a calculus with groups

In th International Symposium on Mathematical Foundations of Com

puter Science August

Fil A Filinski Representing layered monads In POPL ACM Press

FM M Fairtlough and M Mendler An intuitionistic mo dal logic with appli

cations to the formal verication of hardware In Proceedings of Com

puter Science Logic volume of Lecture Notes in Computer

Science SpringerVerlag

FSDF C Flanagan A Sabry B F Duba and M Felleisen The essence of

compiling with continuations In Proceedings of the Conference on

Programming Language Design and Implementation ACM

GJLS D K Giord P Jouvelot J M Lucassen and M A Sheldon FX

reference manual Technical Rep ort MITLCSTR MIT Lab ora

tory for Computer Science

GL DK Giord and JM Lucassen Integrating functional and imp erative

programming In ACM Conference on Lisp and Functional Program

ming ACM Press

GLT JY Girard Y Lafont and P Taylor Proofs and Types Numb er in

Cambridge Tracts in Theoretical Computer Science Cambridge Univer

sity Press

Gor MJC Gordon Denotational Description of Programming Languages

Springer

HD J Hatcli and O Danvy A generic account of continuationpassing

styles In Proceedings of the st Annual Symposium on Principles of

Programming Languages ACM January

HM Graham Hutton and Erik Meijer Monadic parsing in haskell Journal

of Functional Programming July

HT S Helsen and P Thiemann Syntactic typ e soundness for the region

calculus In Workshop on Higher Order Operational Techniques in Se

mantics volume of Electronic Notes in Theoretical Computer Science

Elsevier Septemb er

Hud P Hudak Mo dular domain sp ecic languages and to ols In Fifth

International Conference on Software Reuse pages Victoria

Canada June

Hug John Hughes Restricted Datatyp es in Haskell In Third Haskel l Work

shop Utrecht University technical rep ort

Jac Bart Jacobs Categorical Logic and Numb er in Studies

in Logic and the Foundations of Mathematics North Holland

JHe Simon Peyton Jones John Hughes editors Lennart Augustsson

Dave Barton Brian Boutel Warren Burton Joseph Fasel Kevin Ham

mond Ralf Hinze Paul Hudak Thomas Johnsson Mark Jones John

Launchbury Erik Meijer John Peterson Alastair Reid Colin Runci

man and Philip Wadler Rep ort on the Programming Language

Haskell a Nonstrict Purely Functional Language Available from

httphaskellorg February

JLST S L Peyton Jones J Launchbury M B Shields and A P Tolmach

Bridging the gulf A common intermediate language for ML and Haskell

In Proceedings of POPL ACM

Jon S L Peyton Jones Compiling Haskell by program transformation A

rep ort from the trenches In Proceedings of the European Symposium

on Programming Linkping Sweden numb er in Lecture Notes in

Computer Science SpringerVerlag January

JRtYHG Mark P Jones Alastair Reid the Yale Haskell Group the Oregon Grad

uate Institute of Science and Technology The hugs user manual

Available from httphaskellorghugs

JW Simon Peyton Jones and Philip Wadler Imp erative functional program

ming In th Symposium on Principles of Programming Languages

Charlotte North Carolina January ACM Press

KKR D Kranz R Kelsey J Rees P Hudak J Philbin and N Adams

Orbit An optimizing compiler for Scheme In Proceedings of the ACM

SIGPLAN Symposium on Compiler Construction SIGPLAN Notices

pages

KL D King and J Launchbury Structuring depthrst search algorithms

in haskell In Conf Record nd Symp on Principles of Programming

Languages pages San Francisco California ACM

Lev PB Levy Callbypushvalue a subsuming paradigm extended ab

stract In Typed LambdaCalculi and Applications volume of

LNCS Springer

LH S Liang and P Hudak Mo dular denotational semantics for compiler

construction In ESOP volume of LNCS Springer

LHJ S Liang P Hudak and M Jones Monad transformers and mo dular

interpreters In POPL ACM Press

LJ J Launchbury and S Peyton Jones Lazy functional state threads In

Proceedings of the SIGPLAN Conference on Programming Lan

guage Design and Implementation PLDI June

LS J Launchbury and A Sabry Monadic state Axiomatisation and typ e

safety In Proceedings of the International Conference on Functional

Programming ACM

LW X Leroy and P Weis Polymorphic typ e inference and assignment In

Proceddings of the ACM Conference on Principles of Programming

Languages ACM

Man E Manes Algebraic Theories Graduate Texts in Mathematics

Springer

Man E Manes Implementing collection classes with monads Mathematical

Structures in Computer Science

Min Y Minamide A functional represention of data structures with a hole

In Proceedings of the rd Symposium on Principles of Programming

Languages

MMH Y Minamide G Morrisett and R Harp er Typ ed closure conversion In

Conference Record of the rd Annual ACM SIGPLANSIGACT Sympo

sium on Principles of Programming Languages St Petersburg Florida

ACM January

Mog E Moggi Computational lamb dacalculus and monads In Proceedings

of the th Annual Symposium on Logic in Computer Science Asiloomar

CA pages

Mog E Moggi Notions of computation and monads Information and Com

putation

Mog E Moggi A semantics for evaluation logic Fundamenta Informaticae

Mog E Moggi Metalanguages and applications In Semantics and Logics of

Computation volume of Publications of the Newton Institute Cam

bridge University Press

Mos P Mosses Denotational semantics In J van Leeuwen editor Handbook

of Theoretical Computer Science chapter MIT press

Mos P Mosses Action Semantics Numb er in Cambridge Tracts in The

oretical Computer Science Cambridge University Press

MP E Moggi and F Palumb o Monadic encapsulation of eects A re

vised approach In Proceedings of the Third International Workshop on

HigherOrder Operational Techniques in Semantics Electronic Notes in

Theoretical Computer Science Elsevier Septemb er

MT I Mason and C Talcott Equivalences in functional languages with

eects Journal of Functional Programming

MWCG G Morrisett D Walker K Crary and N Glew From System F to typ ed

assembly language ACM Transactions on Programming Languages and

Systems May

NHH F Nielson H R Hielson and C Hankin Principles of Program Anal

ysis SpringerVerlag

Pey Simon Peyton Jones Tackling the awkward squad monadic in

putoutput concurrency exceptions and foreignlanguage calls in

Haskell In R Steinbrueggen editor Engineering theories of software

construction Marktoberdorf Summer School NATO ASI Series

IOS Press

Pit A M Pitts Op erationallybased theories of program equivalence In

P Dyb jer and A M Pitts editors Semantics and Logics of Computa

tion Publications of the Newton Institute pages Cambridge

University Press

Pita A M Pitts Op erational semantics and program equivalence revised

version of lectures at the international summer scho ol on applied seman

tics This volume Septemb er

Pitb AM Pitts Categorical logic In S Abramsky DM Gabbay and TSE

Maibaum editors Handbook of Logic in Computer Science volume

Oxford University Press

Plo G D Plotkin Callbyname callbyvalue and the lamb da calculus

Theoretical Computer Science pages

Plo G D Plotkin LCF considered as a programming language Theoretical

Computer Science

Sco DS Scott A typ etheoretic alternative to CUCH ISWIM OWHY

Theoretical Computer Science

SF A Sabry and M Felleisen Reasoning ab out programs in continuation

passing style Lisp and Symbolic Computation

Sha Z Shao An overview of the FLINTML compiler In Proceedings of

the ACM Workshop on Types in Compilation Amsterdam ACM

June

SS M Semmelroth and A Sabry Monadic encapsulation in ML In Pro

ceedings of the International Conference on Functional Programming

ACM

Sta I D B Stark Names and Higher Order Functions PhD thesis Com

puter Lab oratory University of Cambridge

TJ JP Talpin and P Jouvelot The typ e and eect discipline Information

and Computation June Revised from LICS

Tof M Tofte Operational Semantics and Polymorphic Type Inference PhD

thesis Department of Computer Science University of Edinburgh

Tol A Tolmach Optimizing ML using a hierarchy of monadic typ es In

Proceedings of the Workshop on Types in Compilation Kyoto March

TT M Tofte and JP Talpin Regionbased memory management Infor

mation and Computation February

Wad P Wadler Comprehending monads Mathematical Structures in Com

puter Science

Wad P Wadler The marriage of eects and monads In International Con

ference on Functional Programming ACM Press

WF A K Wright and M Felleisen A syntactic approach to typ e soundness

Information and Computation Novemb er

Wri A Wright Simple imp erative p olymorphism LISP and Symbolic Com

putation

WT P Wadler and P Thiemann The marriage of eects and monads Sub

mitted to ACM Transactions on Computational Logic