Patrik Jansson
Department of Computing Siene
Chalmers University of Tehnology and Goteborg University
Goteborg, 2000
Funtional Polytypi
Programming
Patrik Jansson
Departmentof Computing Siene
Chalmers University of Tehnology and Goteborg University
Goteborg, Sweden, May 2000
ISBN91-7197-895-X
Patrik Jansson,2000
Doktorsavhandlingar vid Chalmers Tekniska Hogskola
Ny serie nr 1584
ISSN 0346-718x
Computing Siene
Chalmers University of Tehnology and Goteborg University
SE-412 96Goteborg
Sweden
Patrik Jansson
Department of ComputingSiene
Chalmers University of Tehnology and Goteborg University
Abstrat
Many algorithmshave to beimplemented overand over again fordierentdata-
types, either beause datatypes hange during the development of programs, or
beause the same algorithm is used for several datatypes. Examples of suh al-
gorithmsare equalitytests, prettyprinters, and patternmathers,and polytypi
programming is a paradigm for expressing suh algorithms. This dissertation
introdues polytypi programmingfor funtionalprogramminglanguages, shows
how toonstrut and prove properties of polytypi algorithms, presents the lan-
guageextensionPolyPforimplementingpolytypialgorithmsinatypesafeway,
and presents a number of appliations of polytypi programming. The applia-
tionsinludealibraryof basipolytypibuildingbloks,PolyLib,andtwolarger
appliations of polytypi programming: rewriting and data onversion.
PolyP extends a funtional language (a subset of Haskell) with a onstrut for
dening polytypi funtions by indution on the struture of user-dened data-
types. Programs inthe extended languageare translated to Haskell.
PolyLib ontains powerful strutured reursion operators like atamorphisms,
maps and traversals, aswell aspolytypi versions of a number of standard fun-
tions from funtional programming: sum, length, zip, (==), (6), et. Both the
speiation of the library and a PolyP implementation are presented.
The rst larger appliation is aframework for polytypi programmingonterms.
WeshowthataninterfaeoffourfuntionsissuÆienttoexpresspolytypifun-
tionsforpatternmathing,uniationandtermrewriting. Usingthisframework,
atermrewritingfuntionisspeiedandtransformedintoaneÆientandorret
implementation.
In the seond appliation, a number of funtions for polytypi data onversion
are implemented and proved orret. The onversions onsidered inlude pretty
printing,parsing,pakingandunpakingofstrutureddata. Theonversionfun-
tionsare expressed inanembeddeddomainspeilanguagefordata onversion
(ahierarhy of Haskell's onstrutor lasses).
Keywords: Programming languages, Funtional programming, Algebraidata-
types, Polytypiprogramming, Generiprogramming
AMS 1991 subjet lassiation68N15, 68N20
1. Patrik Jansson and Johan Jeuring. A framework for polytypi program-
ming onterms, with anappliation to rewriting. In Workshop on Generi
Programming,2000.
2. Patrik Jansson and Johan Jeuring. Polytypi data onversion programs.
Submitted forpubliation, 2000.
3. P. Jansson and J. Jeuring. Polytypi ompat printing and parsing. In
Doaitse Swierstra, editor, Proeedings of the 8th European Symposium on
Programming, ESOP'99, volume 1576 of LNCS, pages 273{287. Springer-
Verlag, 1999.
4. R. Bakhouse, P. Jansson, J. Jeuring, and L. Meertens. Generiprogram-
ming: Anintrodution. InAdvanedFuntionalProgramming,volume1608
of LNCS, pages 28{115. Springer-Verlag,1999.
5. PatrikJanssonandJohanJeuring. Funtional pearl: Polytypiuniation.
Journal of Funtional Programming, 8(5):527{536,September 1998.
6. P. Jansson and J. Jeuring. PolyLib { a polytypifuntion library. Work-
shop onGeneri Programming,Marstrand, June 1998.
7. PolyP | a polytypi programming language extension. In Conferene
Reord of POPL '97: The 24th ACM SIGPLAN-SIGACT Symposium on
Priniples of Programming Languages,pages 470{482. ACMPress, 1997.
8. J. Jeuring and P. Jansson. Polytypi programming. In J. Launhbury,
E. Meijer, and T. Sheard, editors, Advaned Funtional Programming '96,
volume 1129 of LNCS, pages 68{114. Springer-Verlag,1996.
Available fromthe Polytypi programmingWWW page [49℄.
http://www.s.halmers.se/ ~pat rikj /po ly/
1 Introdution 1
1.1 What is apolytypifuntion? . . . 2
1.2 Polymorphismand polytypism . . . 3
1.3 Why polytypiprogramming? . . . 4
1.4 Sope . . . 5
1.5 Approahes to writingpolytypiprograms . . . 6
1.6 The PolyP system. . . 7
1.7 Overview. . . 7
2 Prelude 9 2.1 Context . . . 9
2.2 The funtiontype . . . 9
2.3 The disjointsum type . . . 10
2.4 The unit type . . . 11
2.5 The pair type . . . 11
2.6 The Haskell bottom . . . 12
2.7 Booleans, truth values and prediates . . . 13
2.8 Computationsthat may fail . . . 15
2.9 Polymorphilists . . . 16
2.10 Overloadingand lasses . . . 17
2.11 Fixed points . . . 17
2.11.1 Fixed point indution. . . 18
2.11.2 Explainingxed point indution . . . 20
3 Basi polytypi programming 23 3.1 The struture of lists . . . 24
3.2 Catamorphisms and fusionfor lists . . . 26
3.3 The struture of trees . . . 29
3.4 Pattern funtors. . . 31
3.5 In and out of aregular datatype . . . 32
3.6 The polytypionstrut . . . 33
3.7 Catamorphisms and maps . . . 35
3.8 Catamorphisms onspei datatypes . . . 37
3.9 Separate: asimple PolyP program. . . 38
3.10 Polytypi laws . . . 40
4 PolyP | a polytypi programming language extension 45 4.1 Type inferene. . . 45
4.1.1 The ore language . . . 46
4.1.2 The polytypilanguageextension . . . 47
4.1.3 Uniation. . . 50
4.1.4 Type heking the polytypionstrut. . . 50
4.2 Semantis . . . 52
4.3 Code generation . . . 55
4.4 Implementation . . . 56
4.5 Conlusionsand future work . . . 56
5 PolyLib | a polytypi funtion library 59 5.1 Desribingpolytypifuntions . . . 60
5.1.1 Notationand naming . . . 60
5.1.2 Library overview . . . 60
5.2 Reursion operators . . . 61
5.3 Zips . . . 64
5.4 Monad operations . . . 67
5.5 Flattenfuntions . . . 69
5.6 Misellaneous . . . 70
5.7 Conlusions . . . 71
6 Rewriting 73 6.1 Introdution . . . 73
6.1.1 An examplerewriting system . . . 74
6.1.2 Polytypi rewriting . . . 75
6.2 A term interfae. . . 76
6.2.1 Terms . . . 76
6.2.2 Polytypi Term instanes . . . 78
6.2.3 Combinators onterms . . . 79
6.2.4 Laws for term ombinators . . . 80
6.3 Substitutions,mathing and uniation . . . 82
6.3.1 Substitutions . . . 82
6.3.2 Mathing . . . 83
6.3.3 Uniation. . . 84
6.4 Rewriting . . . 86
6.4.1 One step rewriting . . . 87
6.4.2 Rewritingtonormal form . . . 88
6.4.3 Conrete xed points . . . 90
6.4.5 EÆieny omparison. . . 95
6.5 Proofs . . . 96
6.5.1 Proofs of term ombinatorlaws . . . 97
6.5.2 Proofs of rewriting transformations . . . 101
6.6 Conlusions . . . 104
7 Polytypi Data Conversion Programs 105 7.1 Introdution . . . 105
7.1.1 Data onversion programs . . . 106
7.1.2 Construtingdata onversion programs . . . 107
7.2 Shape . . . 109
7.2.1 Funtionseparate . . . 109
7.2.2 Funtionombine . . . 110
7.2.3 Funtionombine is the inverse of separate . . . 111
7.3 Arrows and laws . . . 111
7.3.1 Basidenitions and laws for arrows . . . 111
7.3.2 A lass for arrows . . . 114
7.3.3 An inverse lawfor arrow produts . . . 116
7.3.4 Fixed point indution and arrows . . . 117
7.4 Arrowmaps . . . 117
7.4.1 The arrowmaps are inverses . . . 118
7.5 Paking . . . 121
7.5.1 The onstrutionof the paking funtion . . . 123
7.6 Pretty printing . . . 128
7.6.1 More arrowlasses . . . 128
7.6.2 Denition ofpshow and pread . . . 131
7.7 Generating arrow instanes. . . 137
7.7.1 An instane for ArrowReadShow . . . 140
7.8 Results and onlusions. . . 141
8 Related work 145 8.1 BMF = Squiggol . . . 145
8.2 Theories of datatypes . . . 146
8.3 Beyond regulardatatypes . . . 146
8.4 Spei polytypi funtions . . . 147
8.5 Type systems . . . 148
8.6 Implementations . . . 149
8.7 Polytypi transformationsand proofs . . . 149
8.8 ImperativePolytypi Programming . . . 150
Aknowledgments 153
A An implementation of PolyLib 165
A.1 Struturedreursion operators . . . 165
A.2 Crush . . . 166
A.3 Monadireursion operators . . . 167
A.4 Thread . . . 169
A.5 ThreadFuns . . . 170
A.6 Propagate . . . 171
A.7 Zip . . . 171
A.8 Equal . . . 174
A.9 Compare . . . 175
A.10Flatten . . . 176
A.11Sum . . . 177
A.12CrushFuns . . . 177
A.13ConstrutorName . . . 178
Introdution
The ability toname and reuse ommonpatterns of omputationas higher-order
funtions is at the heart of the power of funtional languages. Higher-order
funtionslikemapsandatamorphismsaptureverygeneralprogrammingidioms
that are useful in many ontexts. This kindof polymorphi funtionsenables us
to abstrat away from the unimportant details of an algorithmand onentrate
onits essential struture.
The type of a polymorphifuntion has type parameters, but all monomorphi
instanesofthefuntionanuseidentialode. Ageneralizationistoparametrize
alsothefuntiondenitionontypes. Funtionsthat areparametrizedinthisway
arealledpolytypifuntions [61℄. Equalityfuntions,prettyprintersandparsers,
traversal funtionsand otherreursion ombinatorsare allexamplesofpolytypi
funtions.
Whilea normalpolymorphifuntion is analgorithmthat is independent of the
typeparameters,the lass ofinstanes of apolytypifuntionontains funtions
that are dierent, but whih share a ommon struture. Any algorithm in the
lass an be obtained by instantiating a templatealgorithm with (the struture
of) a datatype.
Other terms used for polytypism in the literature are strutural polymorphism
(Ruehr [94℄), type parametri programming (Sheard [97℄), generi programming
(Bird, de Moor and Hoogendijk [7℄), polynomial polymorphism (Jay [55℄), shape
polymorphism (Jay [56℄) and type indexed funtions (Hinze [35℄). A detailed
overview of polytypiprogrammingin relatedwork is presented inChapter 8.
In the sequel we willassume that the readerhas some knowledgeof a funtional
programming language, preferably Haskell [90℄. This hapter explains briey
what polytypi funtions are, why they are useful and how they an be imple-
mented. It alsodesribesthe sope of this dissertation and presents anoverview
of the followinghapters.
1.1 What is a polytypi funtion?
To give an example of what a polytypi funtion is we show that the denitions
of the funtion sum on dierent datatypes share a ommon struture. The sum
funtion takes a struture ontaining integers and returns the sum of all the
integers in the struture. The normal sum funtion for lists an be dened as
follows in the funtional languageHaskell:
sum ::[Int℄ ! Int
sum [℄ = 0
sum (x :xs) = x +sum xs
We dene sum onthe following datatypes:
data[a℄ = [℄ja:[a℄
dataTree a = Leaf a jBin(Tree a)(Tree a)
dataMaybe a = Nothing jJust a
dataRose a = Fork a [Rose a℄
Weandenethefuntionsumforallofthesedatatypes(instantiatedonintegers)
using atamorphisms. A atamorphism is a funtion that reursively replaes
onstrutorswith funtions. We write ata
D fC
i 7!e
i
g for the atamorphismon
the datatype D a that replaes the onstrutorsC
i
with the expressions e
i .
sum
[℄
:: [Int℄!Int
sum
[℄
= ata
[℄
f[℄7!0;(:)7!(+)g
sum
Tree
:: Tree Int !Int
sum
Tree
= ata
Tree
fLeaf 7!id;Bin 7!(+)g
sum
Maybe
:: Maybe Int !Int
sum
Maybe
= ata
Maybe
fNothing 7!0;Just 7!idg
sum
Rose
:: Rose Int !Int
sum
Rose
= ata
Rose
fFork 7!a l !a+sum
[℄ lg
We an already see some patterns in the parameters of the atamorphism: the
two nullary onstrutors [℄ and Nothing are both replaed by 0 and the two
unary onstrutors Leaf and Just are replaed by the identity funtion id. The
binary onstrutors ((:), Bin and Fork) are replaed by funtions that sum the
subexpressions. Allthedenitionsofsum areinstanesofthefollowingpolytypi
denition of psum:
psum ::Regular d ) d Int !Int
polytypifsum :: f Int Int !Int
= asef of
g +h ! either fsum fsum
g h ! (x;y)!fsum x +fsum y
Empty ! x !0
Par ! id
Re ! id
dg ! psumÆpmap fsum
Const t ! x !0
Figure1.1: The denition of fsum
Funtion fsum is dened (in Figure 1.1) by indution over the pattern funtor
f that aptures the struture of the regular type onstrutor d. The polytypi
denitionof funtionata and the explanationoffuntion fsum willhavetowait
untilthe polytypionstrut is dened inSetion 3.6.
Higher-order funtions and polytypi funtions an be used together to obtain
even more generaldenitions. Exatlythe samestruture asthat usedforpsum,
an beused to denethe polytypifuntion on,whihonatenates all listsin
astrutureof type d [a℄. We justreplae0by[℄and (+)withlistonatenation
(++) inthe denition of fsum to obtainfon.
on ::Regular d ) d [a℄![a℄
on = ata fon
Both psum and on are polytypi funtions and thusparametrized onthe type
onstrutor d. By abstrating over the operator and its unit, we an generalize
psum (fsum) and on (fon) to the polytypifuntion rush (frush).
rush ::Regular d ) (a !a !a)!a !d a !a
rush op e = ata (frush op e)
where fsum = frush (+) 0 and fon = frush (++)[℄. These funtions, and
many others,are desribed in PolyLib (Chapter 5and Appendix A).
1.2 Polymorphism and polytypism
A parametri polymorphifuntion suh as
anbeseenasafamilyoffuntions|oneforeahinstaneofaasamonomorphi
type. Parametriityimpliesthathead anmakenoassumptionsaboutthetypea.
Thusall the funtions inthe family are essentiallythe same.
An ad ho polymorphifuntion suh as
(+)::Num a ) a !a !a
is also a family of funtions, one for eah instane in the Num lass. These
instanes may be ompletely unrelated and eah instane is dened separately.
In almostallases, automatitype inferenean be used tond the appropriate
instane for any given ourrene of the (+) operator.
The polymorphismof a polytypi funtion suh as
psum ::Regular d ) d Int !Int
is somewhere in between parametri and ad ho polymorphism. A polytypi
funtion an be seen as a type indexed family of funtions. A single denition
of psum suÆes, but psum has dierentinstanes in dierent ontexts. Here the
ompilergeneratesinstanesfromthedenitionofthepolytypifuntionandthe
typeintheontextwhereitisused. Apolytypifuntionmayalsobeparametri
polymorphi: funtion size ::Regular d ) d a !Int, whih returns the size of
avalue of anarbitrary datatype,is both polytypiand parametri polymorphi.
Meertens [76℄ gives a nie example of the power of parametri polymorphism:
Suppose we wantafuntiontoswaptwointegers: swap ::(Int;Int)!(Int;Int).
Thisisnotaveryhardproblemtosolve,butthereareinnitelymanytypeorret
but wrongsolutions. (Twoare id and (x;y)!(y +1;x).) Ifwegeneralize this
funtiontothe polymorphifuntionswap ::(a;b)!(b;a),then weget amuh
more useful program and we an't make it wrong while type orret. (Stritly
speakingthisistrueonlyinastronglynormalizinglanguage. Ifwehavebottoms,
or non-terminating omputations, as in CPO and in Haskell, then we an still
write a few non-terminating (wrong) versions.) Similarly, even when a funtion
may be needed only for one spei datatype, it may be helpful to dene it
polytypially toredue the risk of making amistake.
1.3 Why polytypi programming?
Polytypiprogramming oersa numberof benets:
Reusability: Polytypism extends the power of polymorphi funtions to allow
the lass of printing funtions for dierent datatypes an be expressed as
one polytypishow funtion. Thuspolytypifuntionsare verywellsuited
for building programlibraries. PolyLib(Chapter 5) is an example of suh
alibrary.
Adaptivity: Polytypi programs automatially adapt to hanging datatypes.
For example, if we add a onstrutor Node (Tree a) a (Tree a) to the
datatypeTree a,then thesame polytypisum funtionan stillbeused to
sumallintegersinelementsofthe(new)tree type. Thisadaptivityredues
the need for time onsuming and boring rewrites of trivial funtions and
eliminatesthe assoiated riskof making mistakes.
Closure and orthogonality: Currently some polytypi funtions an be used
butnot dened inML (theequality funtion(s))and Haskell(the members
ofthederived lasses). Thisasymmetryanberemovedbyextendingthese
languages with polytypi denitions.
Appliations: Some problems are polytypi by nature: maps and traversals
(Setion 5.4), pretty printing and parsing (Setion 7.6), data ompression
(Setion 7.5), mathing (Setion 6.3.2), uniation (Setion 6.3.3), term
rewriting (Setion 6.4), ...
Provability: More general funtions meansmore general proofs. Ifwe onsider
polytypi proofs, then eah of the earlier benets obtains anadditionalin-
terpretation: weget reusable proofs,adaptiveproofs,less ad ho semantis
of programming languages and new proofs of properties of printing and
parsing (Setion 7.6), paking (Setion 7.5), term rewriting (Setion 6.4)
et.
1.4 Sope
As the title suggests this dissertation is about polytypi programmingfor fun-
tional programming languages. More speially, the programs in this disserta-
tionarewritteninthefuntionalprogramminglanguageHaskell98[90℄extended
with withsupportforpolytypidenitions provided by theauthors languageex-
tension PolyP (Chapter 4).
A polytypi funtion an be applied to values of a large lass of datatypes, but
somerestritions apply. Werequirethat apolytypifuntionisappliedtovalues
ofregular datatypesonly. AdatatypeD aisregularifitisnotmutuallyreursive,
ontainsnofuntion spaes,and ifthe argumentsof thedatatype onstrutoron
the left- and right-hand side in its denition are the same. The olletion of
[a℄,anddierentkindsoftrees. WeusetheonstrutorlassRegular torepresent
the olletionof regular datatypes.
Polytypifuntionsanbedenedonalargerlassofdatatypes, inludingmulti-
pleparameterdatatypes[58℄, mutually reursivedatatypes[14,35,45℄, datatypes
with funtion spaes [26,78℄and nested datatypes [8,34℄but we willnot disuss
these extensions.
1.5 Approahes to writing polytypi programs
There are various ways to implement polytypi programs in a typed language.
(Polytypiprogramsan beimplementedinuntyped languageslikeLisporCbut
without any (stati) type safety. We only onsider strongly typed languages in
this dissertation.) Threepossibilitiesare:
using auniversal datatype;
using higher-orderpolymorphismand onstrutorlasses;
using aspeial syntati onstrut.
Polytypi funtions an be implemented by dening a universal datatype, on
whih wedene the funtionswe wanttohaveavailablefor largelasses ofdata-
types. Thesepolytypifuntionsan beusedonaspeidatatypeif weprovide
translation funtionstoand from the universal datatype. An advantage ofusing
auniversal datatype forimplementingpolytypifuntionsisthat wedonotneed
a language extension for writing polytypi programs. However, using universal
datatypes has several disadvantages: type information is lost in the translation
phase to the universal datatype, and type errors an our when programs are
run. Furthermore, dierent people will use dierent universal datatypes, whih
willmake programreuse more diÆult.
Ifweusehigher-orderpolymorphismandonstrutorlassesfordeningpolytypi
funtions (as in Jones [65℄), then type informationis preserved, and we an use
a funtional language suh as Haskell for implementing polytypi funtions. In
this style all regulardatatypes are represented by the type
dataMu f a = In (f a (Mu f a))
and the lass system is used tooverload funtions like map and ata. However,
writing suh programs is rather umbersome: programs beome luttered with
instanedelarations,andtypedelarationsbeomelutteredwithontexts. And
Beause the rst two solutions towriting polytypifuntions are unsatisfatory,
we have extended (a subset of) Haskell with a syntati onstrut for dening
polytypi funtions. We willuse the name PolyP both for the extension and the
resultinglanguage.
1.6 The PolyP system
PolyPisanextensionofafuntionallanguagethat allowsprogrammerstodene
and use polytypi funtions. The underlying language in this dissertation is
a subset of Haskell and hene lazy, but this is not essential for the polytypi
extension. The extension introdues a new kind of (top level) denition, the
polytypi onstrut,used todene funtionsby indution over the struture of
datatypes. Beause datatype denitions an express sum-, produt-, parametri
and reursive types, the polytypi onstrut must handle these ases.
PolyP type heks polytypivalue denitions and, when using polytypi values,
types are automatially inferred. (Just as in Haskell, sometimes expliit type
annotations are needed to resolve overloading.) The type inferene algorithm
is based upon Jones' theories of qualied types [64℄ and higher-order polymor-
phism [66℄. The semantis of PolyP is dened by adding type arguments to
polytypi funtions in a ditionary passing style. We give a type based transla-
tion from PolyP to Haskell that uses partial evaluation to remove all ditionary
values atompile time. Thus we avoid run time overhead for reating instanes
of polytypi funtions.
The ompilerfor PolyP is still under development, and has a number of limita-
tions. Polytypifuntionsanonlybeappliedtovaluesofregulardatatypes. The
underlying subset of Haskell laks many useful onstruts suh as modules and
instane delarations. Extensions to handle multiple type arguments, mutually
reursive datatypes and allof Haskell are planned for the forthomingsuessor
of PolyP: Generi Haskell [33℄.
1.7 Overview
The dissertation ontains an introdution to polytypi programming,a desrip-
tion of the language extension PolyP and its library PolyLib and two larger
polytypi appliations: term rewriting and data onversion.
Chapter 2 is a non-polytypi prelude to the rest of the dissertation. It denes
notation, useful funtions and laws tobe used in the sequel.
Chapter 3is anintrodutiontofuntional polytypiprogramming. Thishapter
funtions: itdenesatamorphisms,polytypimap funtions,funtionpsumused
in the preeding example and presents the polytypi onstrut whih is used
for dening polytypi funtions by indution over the struture of user-dened
datatypes. This hapter alsopresents some polytypi proof rules and uses these
rules toprove properties about polytypi funtions.
Chapter4brieydesribesthetheoryandimplementationofPolyP:thetypesys-
tem that preserves Haskell-like typeinferene provided the polytypionstrut
isexpliitlytyped, andthesemantisintermsofatranslationofPolyP-programs
into Haskell. The theory from this hapter is not essential for reading the rest
of the dissertation. The hapter is based on the POPL'97 paper PolyP | a
polytypi programming language extension [46℄.
Chapter 5 presents a library of polytypi building bloks that an be used in
appliations. Eah funtion is presented with its type and a brief desription
of what it does and how it is related to other polytypi funtions. The hapter
is a revised version of the paper PolyLib | a polytypi funtion library [51℄.
An implementation of PolyLib in the language extension PolyP is inuded in
Appendix A.
Chapter 6 presents the rst larger polytypi appliation: term rewriting. This
hapter presents aninterfae for polytypiprogramming onterms, and uses this
interfae to desribe polytypi algorithmsfor mathing, uniation and eÆient
termrewritingtogetherwithsomeorretnessproofs. Thehapterisanextended
version of the artile A framework for polytypi programming on terms, with an
appliation to rewriting [52℄.
Chapter7istheseondlargerpolytypiappliation: dataonversion. Itpresents
polytypi funtionsfor maps and traversals, data ompression,and pretty print-
ing. Foreah onversion, a pair ofinverse funtions is onstrutedtogether with
a proof of orretness. The onversion funtions are expressed in an embedded
domainspei languagefor dataonversion. Theembedded languageisdened
asa hierarhy of Haskell's onstrutorlasses, based onHughes' Arrows [42℄.
Chapter8givesanoverviewofpolytypisminrelatedwork. Itdesribestheorigins
ofpolytypism,thedierentapproahesusedtoexpress,typehekandimplement
polytypism and gives many referenes to further readingabout polytypism.
Prelude
This hapter is for the dissertation what the standard prelude is for Haskell: a
olletionof ommonresoures whih an be used everywhere withoutexpliitly
havingtodenethemloallyorimportthem. Thepreludeisdividedintosetions
thatpresentsome notationand afew basidatatypeswith assoiated operations
and laws.
2.1 Context
For speiations, program ode and proofs, we use Haskell [90℄ notation with
a few typographial enhanements toimprove readability. In a few plaes these
enhanements lash with the formalsyntax for Haskell. For example, we use (;)
forforwardomposition(thatis,f ;g =gÆf)althoughHaskellusesthesemiolon
only as a separator. Where possible, inluded program ode is automatially
pretty printed fromHaskell orPolyP soureode toavoid errors.
In ategorytheory, afuntor is amappingbetween ategories that preserves the
algebraistrutureoftheategory. Beauseaategoryonsistsofobjets(types)
andarrows (funtions),afuntoronsistsoftwoparts: adenitionontypes, and
a denition on funtions. We normally work in the ategory CPO of omplete
partialorders and ontinuous funtions between them.
2.2 The funtion type
The Haskell type ofpartial funtionsfroma tob iswritten a !b anda lambda
expression with patterna and body b is written a !b. The identity funtion,
onstant funtion and funtionomposition are dened as follows:
id :: a !a
id x = x
onst :: a !b !a
onst k = k
(Æ) :: (b !)!(a !b)!(a !)
(f Æg)x = f (g x)
Funtions of multiple arguments are normally urried in ontrast to languages
like Ada, Java and SML where funtions normally take a tuple of arguments.
The funtions urry and unurry onvert between these twoviews:
urry :: ((a;b)!)!(a !b !)
urry f x y = f (x;y)
unurry :: (a !b !)!((a;b)!)
unurry f p = f (fst p)(snd p)
2.3 The disjoint sum type
The disjoint sum type Either a b in Haskell onsists of left-tagged elements of
typea,andright-taggedelementsoftypeb,andhasonstrutorsLeft andRight,
whih injet elementsinto the left and rightomponent of a sum respetively.
dataEither a b = Left a jRight b
Left ::a !Either a b
Right ::b !Either a b
Funtion l r r (written either l r in Haskell) is a shorthand notation for ase
analysis. Funtion( r ) is the atamorphismon Either. It takes a funtion l of
type a ! and a funtion r of type b ! , and replaes Left with l and Right
with r:
(r )::(a !)!(b !)!(Either a b !)
(l r r)(Left x) = l x
(l r r)(Right y) = r y
The operator ( + ) is used to apply either l or r inside Left or Right. It is a
two-argument mappingfuntion onEither.
( + )::(a !)!(b !d)!(Either a b !Either d)
(l + r)(Left x) = Left (l x)
The followingfuntionaldenition of ( + ) isequivalent and easier toalulate
with:
l + r = (LeftÆl)r (Right Ær)
Funtion( + ) satises two funtor laws and operator( r ) satises two fusion
laws:
id + id = id
(f + g)Æ(h + i) = (f Æh) + (g Æi)
f Æ(g r h) = (f Æg)r (f Æh)
(f r g)Æ(h + i) = (f Æh) r (g Æi)
2.4 The unit type
The nullaryprodut type and itsonly onstrutor are both writtenas ():
data() = ()
2.5 The pair type
The binary produt type and its elements are written as pairs (a;b). Funtions
fst and snd are the twoprojetions.
data(a;b) = (a;b)
fst (a;b) = a
snd (a;b) = b
The duals of ( r ) and ( + ) are (
) and ( ),respetively.
(
)::(a !b)!(a !)!(a !(b;))
(f
s)x = (f x;s x)
The operator ( ) is the analogueof map on produts.
( )::(a !)!(b !d)!((a;b)!(;d))
(f s)(x;y) = (f x;s y)
By analogy with the denition of ( + ) we have an equivalent funtion level
denition:
Funtion( )satisestwobifuntorlawsandoperator(
)satisestwofusion
laws:
id id = id
(f g)Æ(h i) = (f Æh) (gÆi)
(f
g)Æh = (f Æh)
(gÆh)
(f g)Æ(h
i) = (f Æh)
(gÆi)
2.6 The Haskell bottom
All Haskell types have a bottom element denoting a non-terminating omputa-
tion and we an dene a polymorphi value ? by the following trivial reursive
denition:
?::a
? = ?
Inontrast tomost theoretialframeworks thefuntion type,the empty and the
binary produt typein Haskell are all lifted:
(x !?) 6= ?::a !b
() 6= ?::()
(?;?) 6= ?::(a;b)
Among other things,this meansthat for Haskell:
-expansionis not semantis preserving: if f = ?::a !b, then
x !f x = x !?x = x !? 6= ? = f :
The type() is not aterminal objet asit has twoelements: ? and ().
Andwe do not have surjetive pairing: if p = ?::(a;b),then
(fst p;snd p) = (fst ?;snd ?) = (?;?) 6= ? = p :
To sum up | almost no laws from CPO hold in Haskell! As this would lead to
onsiderableproblems inthe detailedproofs,werestrit ourselves totheunlifted
versions of these types. As we use Haskell for the implementations this means,
stritly speaking, that most of the results presented in this dissertation are not
proved fortheatualrunningode butforidealizedversions. Thishas notturned
2.7 Booleans, truth values and prediates
The booleanvalues False and True are the onstrutorsof the type Bool:
dataBool = False jTrue
Notethat the Haskell type Bool ontainsa leastvalue,?, inadditiontothe two
truth values. When we really need only truth values we use the type Truth =
fFalse;Trueg and onvert from Bool to Truth by identifyingFalse and ?:
b::Bool ! Truth
bTrue = True
b = False
The expression bbmeans \the alulationof b terminates with the value True"
and is pronouned\b is true" for short.
Wehavetheommonoperationsimpliation()),and(^),or(_),andnegation
(:) for alulating with Booleans and with Truth values, and if-expressions to
selet between two expressions. We use the same syntax for operations on Bool
and operations onTruth.
We often work with prediates instead of booleans to simplify alulations. We
oftenuse the same syntax for the pointwise liftedoperations.
false;true :: a !Bool
false = onst False
true = onst True
());(^);(_) :: (a !Bool)!(a !Bool)!(a !Bool)
p ) q = x !p x ) q x
p ^ q = x !p x ^ q x
p _ q = x !p x _ q x
i p thent elsee = x !if p x thent x elsee x
b :: (a !Bool)!(a !Truth)
bp = x !bp x
Asanexampleofthe use oftheliftedbooleanoperationsweanspeify pre-and
post-onditionsfor a funtion f:
bpre ) bpostÆf :
Expandingthe denitions of the liftedoperators this is equivalentto:
Ifthis prediate equals true (that is, for allx the body isTrue),then f satises
itsspeiation.
The Haskell equality test (==)::Eq a ) a !a !Bool isalsolifted:
(===) :: Eq b ) (a !b)!(a !b)!(a !Bool)
f ===g = x !f x ==g x
The liftedversion of the law(f x ==f y) ( (x == y) beomes:
Lemma 2.1 Canel(fÆ):
(f Æg ===f Æh) ( (g ===h)
We willoften reason about funtions that are equal when restrited to a subset
of their domains:
Denition 2.2 Funtion equalityon a subset:
(
===)::Eq a ) (b !Bool)!(b !a)!(b !a)!(b !Truth)
f p
===g = x !bp x ) bf x ==g x
or, equivalently, using the lifted operations:
f p
===g = bp ) bf ===g
We willlater use the following property of ( p
===):
Lemma 2.3 Fator ( p
===):
gÆf pÆf
===h Æf ===(g p
===h)Æf
The liftedversion of b satises the following laws:
Lemma 2.4 Fator out f from b:
bpÆf===bpÆf
Lemma 2.5 Canel(Æf):
bpÆf ( bp
Simplelaws for booleanslift immediatelytoprediates:
Law 2.6 (exp1): (a _ b) ) (a ) ) ^ (b ) )
Law 2.7 (exp2): a ) (b _ ) (a ) b) _ (a ) ).
Laws fori then else:
Lemma 2.8 i then else-fusion:
For all strit f:
f (i b then pelse q) = i b thenf p elsef q
Lemma 2.9 i p then p
(i p thenbpelse x) = (i p then true elsex)
Lemma 2.10 Expressing (_) using i then else:
bp _ q = i bpthen true elsebq
2.8 Computations that may fail
The datatype Maybe a is used to model omputations that may fail to give a
result.
dataMaybe a = Nothing jJust a
Forexample,wean denetheexpression divide m n tobeequaltoNothing ifn
equals zero, and Just (m =n) otherwise. A funtion that handles values of type
Maybe a onsistsof two omponents: aomponent that dealswith Nothing,and
aomponent that deals with valuesof the formJust x.
maybe ::b !(a !b)!Maybe a !b
maybe n j Nothing = n
maybe n j (Just x) = j x
Funtionmaybe isanexample ofa atamorphism. FuntionmapM takes afun-
tion f, and a value of type Maybe a, and returns Nothing in ase the argument
equals Nothing,and Just (f x) inase the argumentequals Just x.
mapM ::(a !b)!Maybe a !Maybe b
FuntionmapM satisestwo funtorlawsand funtionmaybe satisestwofusion
laws:
mapM id === id
mapM f ÆmapM g === mapM (f Æg)
f Æmaybe n j === maybe (f n)(f Æj)
maybe n j ÆmapM f === maybe n (j Æf)
It is sometimes useful tohave prediates totest forJust and Nothing:
isJust;isNothing :: Maybe a !Bool
isJust (Just ) = True
isJust Nothing = False
isNothing Nothing = True
isNothing (Just ) = False
2.9 Polymorphi lists
The polymorphi listdatatype inHaskellis written [a℄ and has a onstrutor [℄
for the empty listand aninx (:) for prepending a value to a list. There is also
syntati sugar for lists: for example [1;2;3℄means 1:2:3:[℄.
data[a℄ = [℄ja:[a℄
The syntaxfor the listonstrutorsisa littledierentfromother datatypes. We
willsometimes use adenition more in linewith otheruser-dened datatypes:
dataList a = Nil jCons a (List a)
Youan think about this just asa dierent syntax for the built-in lists.
The Haskell funtion foldr ()e is a atamorphismfor lists |it replaes uses
of the onstrutor (:)with () and uses of [℄ with e:
foldr ()e [℄ = e
foldr ()e (a:as) = afoldr ()e as
Funtionmap f maps the funtion f overall elementsin alist:
Funtion map satises two funtor laws and funtion foldr satises two fusion
laws: (h is strit)
map id === id
map f Æmap g === map (f Æg)
hÆfoldr f e === foldr g (h e) ( 8x y: h (f x y)==g x (h y)
foldr f eÆmap g === foldr (f Æg)e
Forreferene we present a fewother listfuntions here as well:
null :: [a℄!Bool
null [℄ = True
null ( : ) = False
nil :: b ![a℄
nil x = [℄
singleton :: a ![a℄
singleton x = [x℄
(++) :: [a℄![a℄![a℄
xs++ys = foldr (:)ys xs
2.10 Overloading and lasses
WewilloftenuseHaskell'slasssystem[66℄towritegenerioverloadedode. This
isvisibleintypesasontext)normaltype whereontextliststhelassonstraints
thevariablesinnormaltypemustsatisfy. Anexampleissort ::Ord a)[a℄![a℄
wherea is restrited tobein the lass Ord of types with aomparison operator.
We use the Haskell lass Monad for monadiomputations [102℄.
lassMonad m where
return :: a !m a
(>>=) :: m a !(a !m b)!m b
(>>) :: m a !m b !m b
fail :: String !m a
2.11 Fixed points
For alulations and proofs involving reursively dened values, we oftenuse an
in support for reursive denitions over all types and we an diretly dene a
xed pointombinatorx:
x ::(a !a)!a
x f = f (x f)
We all f an improvement funtion | it takes an approximation of the xed
point toa better approximation.
2.11.1 Fixed point indution
Theorem 2.11 Fixed point fusion:
f Æg = hÆf ) f (x g)==x h
The requirement of the xed point fusion law is often too strong | a weaker
requirement an be obtained by observing that the equality is only needed for a
hain of nite approximations of g:
8i: f (g a
i
) = h (f a
i
)where a
i
= g i
?
This in turnan be expressed indutively:
P (?) ^ 8x: P (x) ) P (g x)
where P (x) = f (g x)==h (f x)
The rolling rule [84℄ is asimple appliation of xed point fusion:
Lemma 2.12 The rolling rule: for all funtions f ::a !b and g ::b !a
x (f Æg)===f (x (g Æf))
In the sequel we will use a powerful xed point law that relates n xed points.
Fortheformulationof thexed pointlawwe needtointroduethe onept ofan
inlusive relation as dened in Shmidt [95℄ (other names used in the literature
are \admissible" and \limitlosed").
Denition 2.13 A relationP is inlusive i for all hains of tuples (a i
1
;:::;a i
n )
(8i: P (a i
1
;:::;a i
n
)) ) P ( G
a i
1
;:::;
G
a i
n )
Inlusiverelationsareusedtoprovepropertiesaboutxed pointsfromproperties
of nite approximations of these xed points. The expression F
i a
i
denotes the
leastupper bound ofthe hain a
i
with respet totheapproximationordering(v)
of the CPO. Tuples are ordered pointwise. A useful soure of inlusive relations
is the following theorem.
Theorem 2.14 A lass of inlusive relations: [95, def. 6.28℄
A relation P isinlusive if P (f
1
;:::;f
n
) has the form:
8d
1 2D
1
;:::;d
m 2D
m :
k
^
i=1 (
l
_
j=1 Q
ij )
where Q
ij
an be either
1. A prediate using only the d
i
as free identiers.
2. An inlusion e
1 v e
2
where e
1
and e
2
are expressions using ontinuous
funtions and only the f
i
and the d
i
as free identiers.
A funtion is ontinuous if it is monotone with respet to the (v) ordering and
if itpreserves leastupperbounds. Allonstrutionsinafuntionallanguagelike
Haskell are ontinuous, but some operators in the semantidomain are not. On
Truth, the operators (^) and (_) are ontinuous but negation (:) is not even
monotone and asa ) b = :a _ b, neitheris ()).
Twoexamples of inlusiverelations are
r
1
:: Bool !Truth
r
1
(b) = bb
r
2
:: (Truth;Truth)!Truth
r
2
(a;b) = a ) b
Proof: Funtionsr
1 andr
2
areinlusive,beauseweanrewritetheirdenitions
tomath the formof Theorem 2.14:
r
1
(b) = bb = (b vTrue) ^ (True vb)
r
2
(a;b) = a ) b = a vb :
Theorem 2.15 Fixed point indution: [95, def. 6.26℄
For every inlusive relation P, and for allimprovement funtions i
1
;:::;i
n :
(P (?;::: ;?) ^ 8f
1 :::f
n : P (f
1
;:::;f
n
) ) P (i
1 f
1
;:::;i
n f
n ))
)P (x i
1
;:::;x i
n )
A typialexample appliationof this theorem isfound inprovingthat two fun-
tions g = x ig and h = x ih are equal on the set where a prediate
p = x ip holds. Note that the prediate is also dened as a xed point.
We use xed point indution with n = 3, the relation P (x;y;z) = x z
===y
and improvementfuntions ig, ih and ip.
Thebaseaseiseasy: theprediate?isnevertrue,andallfuntionsaretrivially
equalon the empty set, sowhat is left isthe following:
Theorem 2.16 x-equality:
(8x y z: x z
===y ) ig x ipz
===ih y) ) x ig xip
===x ih
2.11.2 Explaining xed point indution
Toproveapropertyofaxedpointdenitionusingxed pointindutionwehave
to identify a relation that implies the desired property if instantiated with the
xed points, and whih holds for all approximations of the xed point as well.
Theproofofsuhapropertyissimilartoaproofbynormalindutionandonsists
of a series of steps. We formulate a relation P
0
to be proved, we prove the base
aseand westartworkingonthe indutivease untilweneedapropertythatwe
annot prove without some side ondition. Assuming that the original theorem
is true (and provable) it should be possible toprove the side ondition together
with P
0
. Sothen we formulate a relationP
1
that implies the side ondition, and
strengthen the indutive hypothesis to P = P
0
^ P
1
. This means extra work
inproving a new base ase and indutive ase for P
1
, but on the other hand the
indutive ase for P
0
makesa goodleap forward. We repeat this proedure until
we have an indutive proof of P = P
0
^ ::: ^ P
n
| this trivially implies P
0
and we are done.
If,morespeially,wewanttoprovethatafuntionhasaertainpropertywhen
restrited toapartiularset, whereboththe funtionsand the set are dened as
xed points,thenthenew relationstoprove areoftwokinds|thoserelatingall
the parametersand those restriting onlythe set. Anexample (overed in detail
in Chapter 6) is proving that a rewriting funtion always produes a term in
normalformwhenrestritedtothe setofnormalizingterms. Asweareinterested
denitions, the set-only properties an be proven separately and reused for all
the proofs. This an beviewed asspeializingthe xed point indutionpriniple
to an equality over a spei set, or rather speializing the indutive step to a
known set improvementfuntion i.
A veryuseful set-only property is
InLim ::((a !Bool)!(a !Bool))!(a !Bool)!(a !Truth)
InLim
i
p = bp ) bx i
This restrits the sets we need to onsider to subsets of the xed point (for ex-
amplenite terms,ornormalizing terms). Without this restritionthe indutive
step has to be proven for an arbitrary p and that is often hard. Fortunately,
InLim itself iseasy to prove indutively:
Lemma 2.17 InLim:
If i ::(a ! Bool)! (a !Bool) is an improvement funtion for prediates that
is monotone in the following sense:
8p;q: (bp ) bq) ) (bi p ) bi q)
then InLim
i
an be used as a xed point indution side ondition:
InLim
i
? ^ (8p: InLim
i
p ) InLim
i (i p))
Base ase: InLim
i
? = b? ) bx i = true.
Indutive ase: Byalulation:
InLim
i p
fDenition of InLimg
bp ) bx i
) fMonotoniityof ig
bi p ) bi (x i)
fDenition of x: x i = i (x i)g
bi p ) bx i
fDenition of InLimg
InLim
i (i p)
Basi polytypi programming
The essene of funtional polytypiprogrammingis thatfuntions an be dened
by indution on the struture of datatypes. The struture of a datatype is de-
sribed by means of a pattern funtor that aptures the top level struture of
elements of the datatype. Just as in imperative languages where it is preferable
tousestruturediterationonstrutssuhaswhile-loopsandfor-loopsinsteadof
unstruturedgotos,itisoftenadvantageoustousestruturedreursionoperators
instead of unrestrited reursion when using a funtional language. Strutured
programs are easier toreason about and more amenable to(possibly automati)
optimizations than their unstrutured ounterparts. Two very useful strutured
reursion operators are the atamorphism operator ata and the polytypimap-
ping funtion pmap. This hapter denes not only ata and pmap, but also a
onstrut with whihit ispossible todenenew reursion operators,tailoredfor
spei needs. (Examples of suh operators are the monaditraversal funtions
inChapter 5and the arrow maps and data onversion programs inChapter 7.)
Thishapterisorganizedasfollows: Setions 3.1{3.3explainthe strutureoftwo
example datatypes (lists and binary trees) in terms of pattern funtors. These
setions also introdue atamorphisms, maps and fusion laws for the example
datatypes, anduse fusiontoproveafew laws inaalulationalstyle. Setion3.4
denes regulardatatypesandshowshowpatternfuntorsareusedtoapturethe
struture ofregulardatatypes. Setion3.5denes the isomorphismsinn andout
thatonvert valuesbetweenaregulardatatypeandthetoplevelstrutureofthat
datatype. Setion 3.6 introdues the polytypi onstrut to express polytypi
funtions by indution over pattern funtors. The denition of the polytypi
sum funtion psum from the introdution is used as an example. Setion 3.7
denes polytypi atamorphisms and maps and Setion 3.8 explains how use
a atamorphism as an evaluator for a small expression language. Setion 3.9
presents a self-ontained polytypi program, together with the ode that the
PolyP generates for that program. Finally, Setion 3.10 states and proves some
polytypi funtion laws.
3.1 The struture of lists
Consider the datatype List a that is dened by
dataList a = Nil jCons a (List a):
This datatype an be viewed asthe xed point with respet tothe seondargu-
mentof the datatype FList a r dened by
dataFList a r = FNil jFCons a r :
The datatype FList a r desribes the struture of the datatype List a. Note
that FList has one argument more than List. The extra argument is used to
represent the reursive ourrene of the datatype List a in the right-hand side
of its denition. Beause we are only interested in the struture of List a, the
names ofthe onstrutorsof FList are not important. As an elementof FList is
either a nullary onstrutor or a binary onstrutor with its two arguments, we
an instead represent the type FList by:
type FList a r = Either ()(a;r)
WeallFList apatternfuntor asitapturesthereursionpatternofadatatype.
Wenowabstrat fromtheargumentsa andr toobtainavariablefreedesription
of FList. We represent the rst argument by the pattern funtor Par and the
seond argument by Re.
type Par a r = a
type Re a r = r
The type onstrutors in FList are lifted to work on pattern funtors: Either is
lifted to +, the pair type onstrutor ( ; ) is lifted to and the unit type () is
liftedto Empty.
type (f +g)a r = Either (f a r)(g a r)
type (f g)a r = (f a r;g a r)
type Empty a r = ()
As usual, binds stronger than +. Using these pattern funtor onstrutors we
an express FList ina variable freeform.
The initial objet in the ategory of FList a-algebras (that is, the xed point
of FList with respet to its seond omponent) models the datatype List a.
The initialobjet onsists of two parts: the datatype List a, and a single strit
onstrutor funtioninn
List
, that ombines the onstrutors Nil and Cons.
inn
List
::FList a (List a)!List a
inn
List
= onst Nil r unurry Cons
As anexample, the listontainingonly the integer 3,Cons 3Nil, is represented
by inn
List
(Right (3;inn
List
(Left ()))). Funtionout
List
is the inverse of funtion
inn
List .
out
List
::List a ! FList a (List a)
out
List
Nil = Left ()
out
List
(Cons a b) = Right (a;b)
In the polytypi programming system PolyP these funtions are automatially
suppliedby the system for eahuser-dened datatype.
The pattern funtor FList takes two types and returns a type. FList is a bi-
funtor, whih is witnessed by the existene of a orresponding ation, alled
fmap2
FList
, on funtions. Funtion fmap2
FList
takes two funtions and returns a
funtion.
fmap2
FList
::(a !)!(b !d)! (FList a b !FList d)
fmap2
FList
p r = id + p r
Thatfmap2
FList
isindeedabifuntorfollowsimmediatelyfromtheorresponding
laws for( + )and ( ).
fmap2
FList
id id === id
fmap2
FList
f gÆfmap2
FList
h i === fmap2
FList
(f Æh)(gÆi)
Asanexampleofaprogramwrittenusingtheombinatorsdenedsofarweshow
map
List
f xs that applies funtion f toall elementsof the listxs:
map
List
:: (a !b)!(List a !List b)
map
List
f = inn
List
Æfmap2
FList
f (map
List
f)Æout
List
Funtion map
List
is really the same funtion as map in Haskell but we dene it
dierently here to allowfor a simplegeneralization tothe polytypiase.
Just asFList and fmap2
FList
formafuntor,sodoList andthe funtionmap
List :
map
List
id === id
map f Æmap g === map (f Æg)
3.2 Catamorphisms and fusion for lists
Funtion size
List
returns the number of elements in a List a (orresponding to
thefuntionlength inHaskell). Theresultofapplyingsize
List
toanargumentlist
an be omputed by replaing uses of the onstrutor Nil by 0, and uses of the
onstrutor Cons by 1+.
Cons 17 (Cons 3 (Cons 8 Nil ))
1+ (1+ (1+ 0 ))
Thusthesizeofthislistis3. Weuseahigher-orderfuntiontodesribefuntions
that replaeonstrutors by funtions: the atamorphism. The atamorphismis
abasistruturedreursionoperatorandonlistsitisequivalenttofuntionfoldr
inHaskell:
foldr f e = ata
List
where ::FList a b !b
= onst e r unurry f
The atamorphismata
List
replaes Nil by e, and Cons by f.
Cons 17 (Cons 3 (Cons 8 Nil ))
f 17 (f 3 (f 8 e ))
Funtionata
List
isdened usingfuntion out
List
to avoidadenition by pattern
mathing. Funtionfmap2
FList
id (ata
List
f) applies ata
List
f reursively to the
rest of the list.
ata
List
::(FList a b !b)!List a !b
ata
List
f = f Æfmap2
FList
id (ata
List
f)Æout
List
The theoretialjustiationfor this denition isthat inthe ategory of FList a-
algebrastheFList a-algebra(List a;inn
List
)isaninitialobjet. Thismeansthat
thereisauniquearrowfrom(List a;inn
List
)toeveryFList a-algebra(b;f). This
unique arrow is the funtion ata
List
f. The initiality of this algebra alsomeans
that ata
List inn
List
is the identity funtionon List a.
Asexamplesweuse funtionata
List
todenethe funtionsize
List
(orresponding
tolength ::[a℄!Int inHaskell) and listonatenation (++).
size
List
:: List a !Int
size
List
= ata
List
(onst 0 r in)
wherein ( ;n) = 1+n
(++) :: List a !List a !List a
xs++ys = ata (onst ys r unurry Cons)xs
Funtionata
List
satisestheso-alledfusionlaw. Thefusionlawgivesonditions
underwhihintermediatevaluesproduedbyaatamorphisman beeliminated.
Law 3.1 List-fusion: for strit h,
hÆata
List
f = ata
List
g ( hÆf = g Æfmap2
FList id h :
UsingList-fusion wean prove alemma relatingsize
List
and (++).
Lemma 3.2 The size
List
-(++)-lemma:
size
List
(xs ++ys) = size
List
xs +size
List ys :
Proof: In the alulations we abbreviate size
List
with #.
#(xs ++ys) = #xs +#ys
( fAbstrat fromxs g
#Æ(++ys) = (+(#ys))Æ#
( fAssume both sides an be writtenas a atamorphismg
#Æ(++ys) = ata
List
(n r ) = (+(#ys))Æ#
( fTwo subalulationsusing List-fusiong
True
In the rst subalulation we fuse #with (++ys).
# Æ(++ys) = ata
List
(n r )
fDenition of (++ys)g
# Æata
List
(onst ys r unurry Cons) = ata
List
(n r )
( fFusiong
# Æ(onst ys r unurry Cons) = (n r )Æfmap2
FList id#
fDenition of fmap2
FList g
fLaws for (r )g
(# Æonst ys) r (# Æunurry Cons) = n r (Æ(id #))
fSplit the ( r )sand simplifyg
# Æonst ys = n ^ # Æunurry Cons = Æ(id #)
fIntrodue arguments: ()and (x;n)g
#ys = n () ^ #(Cons x xs) = (x;#xs)
fLet n = onst (#ys)g
True ^ 1+ #xs = (x; #xs)
fLet = ing
True
In the seond subalulation welet m = #ys and we fuse(+m) with #.
(+m)Æ # = ata
List
(n r in)
fDenition of #g
(+m)Æata
List
(onst 0r in) = ata
List
(n r in)
fFusiong
(+m)Æ(onst 0 r in) = (n r in)Æfmap2
FList
id (+m)
fDenition of fmap2
FList g
(+m)Æ(onst 0 r in) = (n r in)Æ(id + (id (+m)))
fLaws for (r )g
((+m)Æonst 0) r ((+m)Æin) = n r (inÆ(id (+m)))
fSplit the ( r )sand simplifyg
(+m)Æonst 0 = n ^ (+m)Æin = inÆ(id (+m))
fIntrodue arguments: ()and (x;n)g
m = n () ^ (in (x;n))+m = in (x;n+m)
fDenitions of n and ing
m = m ^ 1+n+m = 1+n +m
fTriviallyg
True
3.3 The struture of trees
The datatype Tree a is dened by
dataTree a = Leaf a jBin (Tree a)(Tree a)
Applying the sameproedure as forthe datatypeList a,we obtainthe following
funtor that desribes the struture of the datatype Tree a.
FTree = Par +ReRe
Funtions inn
Tree
andout
Tree
are dened inthe samewayasfuntionsinn
List and
out
List .
inn
Tree
::FTree a (Tree a)!Tree a
inn
Tree
= Leaf r unurry Bin
out
Tree
::Tree a ! FTree a (Tree a)
out
Tree
(Leaf a) = Left a
out
Tree
(Bin a b) = Right (a;b)
Thefuntionsmap
Tree
andata
Tree
aredenedintermsoffuntionsinn
Tree ,out
Tree
and fmap2
FTree :
fmap2
FTree
::(a !)!(b !d)!(FTree a b !FTree d)
fmap2
FTree
p r = p + r r
map
Tree
::(a !b)!(Tree a !Tree b)
map
Tree
f = inn
Tree
Æfmap2
FTree
f (map
Tree
f)Æout
Tree
ata
Tree
::(FTree a b !b)!(Tree a !b)
ata
Tree
f = f Æfmap2
FTree
id (ata
Tree
f)Æout
Tree
Note that the denitions of map
Tree
and ata
Tree
are almost idential to the def-
initions map
List
and ata
List
, only the indies are dierent. Funtion size
Tree is
dened by
size
Tree
:: Tree a !Int
size
Tree
= ata
Tree
(onst 1 r unurry (+))
Thefuntion atten
Tree
,whihreturnsalistontainingthe elementsof theargu-
menttree, an also be dened using funtion ata
Tree :
atten
Tree
:: Tree a ![a℄
atten
Tree
= ata
Tree
(singleton r unurry (++))
The fusionlawfor trees looks the same as the fusionlawfor lists:
Law 3.3 Tree-fusion: for strit h,
hÆata
Tree
f = ata
Tree
g ( hÆf = gÆfmap2
FTree id h :
We an use this law toprovethat size
List
Æatten
Tree
= size
Tree .
# Æatten
Tree
= size
Tree
fBy denition, introduingthe abbreviations and g
# Æata
Tree
= ata
Tree
( fFusiong
# Æ = Æ(fmap2
FTree id #)
fBy denition of fmap2
FTree g
# Æ = Æ(id + (# #))
fNew abbreviations: =
1 r
2
and =
1 r
2 g
# Æ(
1 r
2
) = (
1 r
2
)Æ(id + (# #))
fLaws for (r )g
(# Æ
1
) r (# Æ
2
) = (
1
Æid)r (
2
Æ(# #))
fSplit the ( r )sand simplifyg
# Æ
1
=
1
^ # Æ
2
=
2
Æ(# #)
fIntrodue arguments,impliitly 8-quantiedg
#(
1
x) =
1
x ^ #(
2 (l;l
0
)) =
2
(#l; #l 0
)
fDenition of
i
and
i g
#[x℄ = 1 ^ #(l ++l 0
) = #l + #l 0
fLemma 3.2g
True ^ True
3.4 Pattern funtors
A pattern funtor aptures the (top level) struture of a datatype. We repre-
sent a pattern funtor in a variable free form by means of a number of funtor
onstrutors. We have already introdued Par for the datatype parameter, Re
for the reursive parameter, Empty for the empty produt and (+) and () for
lifted versions of Either and (;) and we have used them to dene the pattern
funtorsforlistsand trees. In general,PolyP'spatternfuntorsaregenerated by
the followinggrammar:
f;g;h ::= g +h jg h jEmpty jPar jRe jdg jConst t
where d generates regular datatype onstrutors, and t generates monomorphi
types. Wenote the following about the funtor onstrutors:
The pattern funtor for a datatype with more than two onstrutors is
represented by a nested binary sum assoiating tothe right. Therefore, in
theonrete syntax,theonstrutor+isright-assoiative,sothatf +g+h
meansf +(g+h). Construtor+mayonlyour attop level,sof (g+h)
isanillegalfuntor. Thisrestritionorrespondstothesyntatirestrition
inHaskellwhihsaysthatthevertialbarjthatseparatesonstrutorsmay
onlyour atthe top level of datatypedenitions.
Construtor is right-assoiativeand binds stronger than +.
The onstrutor Empty isthe empty or nullaryprodut.
Composition of funtors d and g is denoted by dg and is only dened
for aunary funtor d and abinary funtor g. Funtoromposition isused
to desribe the struture of types that are dened in terms of other user-
dened datatypes, suhas the datatype of rose-trees:
dataRose a = Fork a (List (Rose a))
--FRose = Par (ListRe)
ThepatternfuntorConst t denotesaonstantpatternfuntorwithvaluet.
The t stands for a monotype suh as Bool, Char or (Int;[Float℄). This
is used when a datatype denition mentions a type other than the type
parameteranddatatypeitself. Anexampleisthe strutureof thefollowing
simple datatype of types:
dataType a = Con String jVar a jFun (Type a)(Type a)
--FType = Const String +Par +ReRe
List
= FList = Empty +Par Re
Tree
= FTree = Par +ReRe
Rose
= FRose = Par (ListRe)
Type
= FType = Const String +Par +ReRe
Figure 3.1: Examples of patternfuntors.
The type ontextBifuntor f ) isused toindiatethat f isapatternfuntor.
Every regular reursive datatype d a in Haskell is impliitly dened as a xed
point of a pattern funtor
d
a, that is d a
= (
d
a). PolyP provides a type
onstrutor FuntorOf d (we use
d
as a shorthand) for this pattern funtor.
Pattern funtors for the types dened in this hapter are summarized in Fig-
ure 3.1. A datatype d a is regular(satisesRegular d)if itontains no funtion
spaes, and if the argument of the type onstrutor d is the same on the left-
and right-handside of itsdenition. Foreah regulardatatype d a,PolyPauto-
matially generates
d
using roughly the same steps as those used manuallyfor
FList and FTree in previous setions. Pattern funtors are only onstruted for
datatypes dened by means of the dataonstrut. If,somewhere ina program,
apolytypifuntionisappliedtoavalueof typeMaybe (List a),then PolyPwill
generate an instane of the polytypi funtion on the datatype Maybe b (with
b = List a), not onthe type (MaybeList)a.
Aregulardatatypeisdened asthexed pointofapatternfuntor. Thepattern
funtor
d
may, in turn, referto other (previously dened) regular datatypes in
the dg ase. Thus the desriptions of regular datatypes and pattern funtors
are mutually reursive. In pratie, this means that most polytypi denitions
are given as two mutually reursive bindings | one for the datatype level and
one forthepatternfuntorlevel. Similarly,laws forpolytypifuntionsare often
proved bymutualindutionoverthe grammarsforregulardatatypesandpattern
funtors. This indution is well-founded as we don't allow mutually reursive
datatypesand thusadatatypeanonlyrefertoadatatypethatisdened earlier.
In the rest of the paper we always assume that d a is a regular datatype and
that f is a pattern funtor, and we often omit the ontexts (Regular d )
or Bifuntor f ) ) from the types for brevity. This is purely a notational
onvention in the dissertation, expliit types in atual PolyP programs must
ontain the properontext.
3.5 In and out of a regular datatype
In the denition of a funtion that works for an arbitrary (as yet unknown)
against values. Instead, we use two built-in funtions, inn and out, to onstrut
and destrut a value of an arbitrary datatype from and to its top level om-
ponents. Funtions inn and out are the fold and unfold isomorphisms showing
d a
=
d
a (d a).
inn ::Regular d )
d
a (d a)!d a
out ::Regular d ) d a !
d
a (d a)
Theorem 3.4 Funtions inn and out are inverses.
For every Regular datatype d a:
innÆout ===id ::d a !d a
out Æinn ===id ::
d
a b !
d a b
Note that funtions inn and out are only dened for Regular datatypes d a.
PolyPautomatiallygenerates instanes ofinn and out forallregulardatatypes.
Example instanes were given in Setions 3.1 and 3.3.
3.6 The polytypi onstrut
PolyP introdues anew onstrut polytypifor dening polytypifuntions by
indution overpattern funtors:
polytypip ::[Bifuntor f )℄t = [x
1 :::x
n
!℄asef of ff
i
!e
i g
Here p is the name of the value being dened, t is its type, f is a funtor vari-
able, f
i
are funtor patterns and e
i
are PolyP expressions. The optional funtion
abstration x
1 :::x
n
! is syntati sugar for a polytypi denition with this
abstration in eah of the branhes e
i
. The expliit type in the polytypion-
strut is needed beause we annot in general infer the type from the ases. As
the ase analysis is over pattern funtors, f must be restrited by the ontext
Bifuntor f ),but it is optionalinthe syntax.
The informal meaning is that we dene a funtion that takes (a representation
of) a pattern funtor as its rst argument. This funtion selets the expression
in the rst branh of the ase mathing the funtor, and the expression may in
turnuse thepolytypifuntion(onsubfuntors). Thusthepolytypionstrut is
a(reursive) templatefor onstrutinginstanes of polytypifuntions given the
pattern funtor of a datatype. The funtor argument of the polytypi funtion
neednot(andannot)besuppliedexpliitlybutisinsertedbytheompilerduring
psum ::Regular d ) d Int !Int
psum = ata fsum
polytypifsum :: f Int Int !Int
= asef of
g +h ! fsum r fsum
g h ! (x;y)!fsum x +fsum y
Empty ! x !0
Par ! id
Re ! id
dg ! psumÆpmap fsum
Const t ! x !0
Figure 3.2: The denition of psum
Asanexamplewetakethepolytypisumfuntiondisussed alreadyintheintro-
dution. Funtion psum (dened inFigure 3.2) sums the integers in a struture
with integers. The denitions of ata and pmap are given later in Setion 3.7.
When psum is used on an element of type Tree Int, the ompiler produes the
ode in Figure3.3for psum
Tree
and fsum
FTree
. Together with the ode generated
psum
Tree
:: Tree Int !Int
psum
Tree
= ata
Tree fsum
FTree
fsum
FTree
:: Either Int (Int;Int)!Int
fsum
FTree
= fsum
Par
r fsum
ReRe
fsum
Par
:: Int !Int
fsum
Par
= id
fsum
ReRe
:: (Int;Int)!Int
fsum
ReRe
= (x;y)!fsum
Re
x +fsum
Re y
fsum
Re
:: Int !Int
fsum
Re
= id
Figure3.3: GeneratedHaskell ode for psum
Tree
and fsum
FTree
for ata
Tree
(presented later in Figure 3.5), this is a omplete denition of the
instane psum
Tree
. Funtion fsum
ReRe
an be rewritten as unurry (+) and,
summinga tree:
psum
Tree
::Tree Int !Int
psum
Tree
= ata
Tree
(id r unurry (+))
Asexpeted,psum
Tree
isaTree-atamorphismthatreplaes theonstrutorLeaf
with id and the onstrutor Bin with (+).
3.7 Catamorphisms and maps
Thissetiondenes the funtionsata andpmap thatwere used inthedenition
of funtion psum inFigure 3.2.
The atamorphism, or generalized fold, on a datatype takes as many funtions
as the datatype has onstrutors (ombined into a single argument by means of
funtion(r )),andreursivelyreplaes onstrutorfuntionswithorresponding
argument funtions. It is a generalization to arbitrary regular datatypes of the
funtionfoldr that isdened onlists. In spiteof itsgenerality,funtionata an
be dened in just one line in terms of the funtor map, fmap2 (dened later in
Figure3.4):
ata ::Regular d ) (
d
a b !b)!(d a !b)
ata f = f Æfmap2 id (ata f)Æout
Funtion out makes the top level struture of the input expliit, fmap2 applies
(ata f) reursively to the immediate substrutures, and f ombines the results
ofthe reursive allsintothe nalresult. Exeptfor theindies,the denitionof
the polytypi ata is the same as the instanes onList a and Tree a. Similarly,
we an dene apolytypiversion of map:
pmap ::Regular d ) (a !b)!(d a !d b)
pmap p = innÆfmap2 p (pmap p)Æout
Funtion pmap p applies funtion p toall elements of type a in a value of type
d a. Funtionout takes the argumentapart, fmap2 appliesf toparameters and
(pmap f)reursivelytosubstruturesandinn putsthepartsbaktogetheragain.
We all it pmap to avoid a name lash with the normal Haskell funtion map.
The typesof ata and pmap are best explainedby ommuting diagrams:
d a
out
-
d
a (d a)
b ata f
?
d a b fmap2 id (ata f)
?
d a
out
-
d
a (d a)
d b pmapf
?
d
b (d b) fmap2 f (pmap f)
?
As explained in the prelude, a funtor is a mapping between ategories that
preservesthealgebraistrutureoftheategory. Asaategoryonsistsofobjets
(types) and arrows (funtions), a funtor onsists of two parts: a denition on
types, and a denition on funtions. A pattern funtor in PolyP is a funtion
that takes twotypes and returns a type. The part of the funtor that takes two
funtions and returnsa funtion isalled fmap2,see Figure3.4.
polytypifmap2::(a !)!(b !d)!(f a b !f d)
= p r !asef of
g+h ! fmap2p r + fmap2 p r
gh ! fmap2p r fmap2p r
Empty ! id
Par ! p
Re ! r
dg ! pmap (fmap2p r)
Const t ! id
Figure3.4: The denition of fmap2.
Funtionfmap2
g
isthe funtionationof thepatternfuntorg,andwean show
that pmap
d
isthe funtionationof the typeonstrutor d,viewed asafuntor.
As an example of an instane, Figure 3.5presents the ode generated by PolyP
for ata
Tree
. Funtion out
Tree
was dened in Setion3.3.
ata
Tree
:: (Either a (b;b)! b)!Tree a !b
ata
Tree
i = i Æfmap2
FTree
id (ata
Tree
i)Æout
Tree
fmap2
FTree
:: (a !b)!( !d)! Either a (;)!Either b (d;d)
fmap2
FTree
= p r !fmap2
Par
p r + fmap2
Re Re p r
fmap2
Par
:: (a !b)!( !d)! a !b
fmap2
Par
= p r !p
fmap2
ReRe
:: (a !b)!( !d)! (;)!(d;d)
fmap2
ReRe
= p r !fmap2
Re
p r fmap2
Re p r
fmap2
Re
:: (a !b)!( !d)! !d
fmap2
Re
= p r !r
Figure 3.5: Generated ode for ata
Tree
and fmap2
FTree
Funtionfmap2 andfuntionpmap aremutuallyreursivethroughthedg ase.