• Aucun résultat trouvé

We propose a simple type-lass system extensionto allow the programmerto writeriher ontextsthan is urrently possible

N/A
N/A
Protected

Academic year: 2022

Partager "We propose a simple type-lass system extensionto allow the programmerto writeriher ontextsthan is urrently possible"

Copied!
13
0
0

Texte intégral

(1)

RalfHinze

InstitutfurInformatik III

Universitat Bonn

Romerstrae164, 53117Bonn, Germany

email: ralfinformatik.uni-bonn.de

SimonPeyton Jones

Mirosoft Researh Ltd

St George House,1 GuildhallSt

CambridgeCB23NH, England

email: simonpjmirosoft.om

Abstrat

Generiprogramming allows youto writea funtionone,

and use it many times at dierent types. A lot of good

foundationalworkongeneri programminghasbeendone.

Thegoalofthispaperistoproposeapratialwayofsup-

porting generiprogramming within the Haskell language,

withoutradiallyhangingthelanguageoritstypesystem.

Thekeyidea istopresent generiprogrammingasariher

languageinwhihto writedefaultmethoddenitions ina

lassdelaration.

Onthe way, weame aross aseparate issue, onern-

ingtype-lassoverloadingwhere higherkindsare involved.

We propose a simple type-lass system extensionto allow

the programmerto writeriher ontextsthan is urrently

possible.

Thispaperappearsintheproeedingsofthe2000Haskell

Workshop,Montreal. ToappearinEletroniNotesinThe-

oretialComputer Siene,Elsevier,2001.

1 Introdution

Ageneri,orpolytypi,funtionisonethattheprogrammer

writesone,butwhihworksovermanydierentdatatypes.

Thestandardexamplesareparsingandprinting,serialising,

takingequality,ordering,hashing,andso on. There islots

ofworkongeneriprogramming[2,8 ,1,6℄.

Inthispaperwepresentthedesignandimplementation

of anextensionto Haskellthat supports generi program-

ming.AtrstsightitmightseemthatHaskell'stypelasses

are inompetition with generi programming| after all,

both onern funtions that work over many data types.

Butwe havefound thattheyanbe ombinedverygrae-

fully,oeringasmoothupwardextensiontoHaskell.

Onthewaywedesribeanorthogonal,butomplemen-

taryidea. Haskellallows oneto denehigher-orderkinded

datatypesforwhihitisimpossibletodene,forexample,

anequality instane. Thisseems unfortunate: onepart of

the language ismore powerful thananother. Wedesribe

amodest extensionof Haskell's type-lass system that re-

movesthisdiÆulty.

Morespeially,ourontributionsarethese:

2 We present the language design for an extension to

Haskellthatsupportsgeneriprogramming(Setions2{

6). Generifuntionsappearsolelyinlassdelarations.

2 We desribe an entirely separate extension that lets

onewrite ertain instanedelarations for higher-order

kinded data types that are simply inexpressible in

Haskell98(Setion7).

2 Wedisusstheimplementationofbothparts.

The rst part of this paper is a follow-up to [4 ℄; the new

ahievementsaredetailedinSetion8.

2 Setting the sene

Inthissetionwesettheontextforourproposal.Webegin

byreviewingHaskell'stype-lassoverloadingmehanism.

2.1 A briefreviewoftype lassoverloading

Haskell supports overloading, based on type lasses. For

example,thePreludedenesthelassEq:

lassEqtwhere

( );(6 ) :: t!t!Bool:

Thisdenestwooverloadedtop-levelfuntions,( )and(6 ),

whosetypesare

( );(6 ) :: (Eqt))t!t!Bool:

Beforeweanuse( )onvaluesof,sayInt,wemustexplain

howtotakeequality overInt values:

instaneEqIntwhere

( ) = eqInt

(6 ) = neInt:

Here we supposethat eqInt::Int !Int !Bool,andsim-

ilarly neInt are provided from somewhere. The instane

delarations says \the ( ) funtion at type Int is imple-

mentedbyeqInt".

Howanwetakeequalityofpairsofvalues? Presumably

byomparingtheir omponents;butthat requiresequality

overtheomponenttypes:

instane(Eqa;Eqb))Eq(a;b)where

(x1;y1) (x2;y2) = (x1 x2)^(y1 y2)

(x1;y1)6 (x2;y2) = (x1 6 x2)_(y16 y2):

Itisabitannoyingtokeephavingtowriteodeforthe(6 )

method,beauseitissimplythenegationoftheodeforthe

( )method,soHaskellallowsyoutowriteadefaultmethod

inthelassdelaration:

lassEqtwhere

( );(6 ) :: t!t!Bool

x16 x2 = not (x1 x2):

Now, ifyougive aninstane delarationfor Eq that laks

a denition for (6 ), Haskell\lls in" the missing method

(2)

weanwrite:

instane(Eqa;Eqb))Eq(a;b)where

(x1;y1) (x2;y2) = (x1 x2)^(y1 y2)

andgetjustthesameeetasbefore. Youanevenspeify

adefaultmethodforbothmethods:

lassEqtwhere

( );(6 ) :: t!t!Bool

x

1 x

2

= not(x

1 6 x

2 )

x

1 6 x

2

= not(x

1 x

2 ):

Inaninstanedelaration,youannoweither giveadeni-

tionfor( ),or adenitionfor(6 ),orboth. Ifyouspeify

neither,thenyouwillgetaninniteloop,unfortunately!

If you give an instane delaration without speifying

ode for method op, and the lass hasno default method

forop,theninvokingthemethodwillhalttheprogramwith

anerrormessage. Itisnotaompile-timeerror;sometimes

amethodjustdoesn't makesensefor apartiularinstane

type.

2.2 Overloadingisnot generiprogramming

Haskellasitstandsdoesnotsupportgeneri,orpolytypi,

programming.Inpartiular,supposeyoudeneanewdata

type:

dataWibble = WagIntjWugBool:

Itis \obvious"howto takeequality overWibble,and sup-

portforgeneriprogrammingwouldallowustospeifythis

\obvious"preisely. InHaskell,however,youhavetogivean

expliitinstanedelaration, ontainingtheodeforequal-

ity:

instaneEqWibblewhere

(Wagi1) (Wagi2) = i1 i2

(Wugb1) (Wugb2) = b1 b2

w1 w2 = False:

Crankingoutthissortofboilerplateodeissotiresomethat

Haskellprovidesspeialsupport|theso-alled\deriving"

mehanism|forahandfulofbuilt-inlasses. Inpartiular,

forEqyousay

dataWibble = WagIntjWugBoolderiving(Eq):

The\deriving(Eq)"parttellsHaskelltogeneratethe\ob-

vious"odeforequality.What\obvious"meansisspeied

informally inan Appendixof the languagedenition [15 ℄.

This is all rather ad ho, and in partiular it only works

foraxedsetofbuilt-inlasses(Eq,Ord,Enum,Bounded,

Read,Show,andIx).

2.3 Generalising defaultmethods

Whatwe seek,then,is anautomatimehanismthat \lls

in"asuitableimplementationforthemethodsofaninstane

delaration. But wait a minute! That's what a default

methoddoes! Indeedsobut,as wehavealreadyremarked,

default methods as they stand are too weak. If we write

merely:

instaneEqWibble

wewould,asremarkedearlier, justgetaninniteloop. We

havetoprovidesomerealodesomewhere! What wewant

isariherlanguageinwhihtowritedefaultmethods.That

iswhatweturnourattentiontonow.

Fromalanguage-designpointofview,ourstoryisthis: pro-

viding a riher language for default method denitions in

a lass delaration gives an elegant way to extend Haskell

withthepowerof generiprogramming. Wewilljustifythis

statementmorefullyinSetion9,butrstwemustpresent

ourdesign.

3.1 Twoexamples

Weadoptwithminorhangestheproposalin[4 ℄. Twoex-

ampleswillservetogivetheidea. First,hereistheEqlass

augmentedwithgeneriequality:

lassEqtwhere

( );(6 ) :: t!t!Bool

--generidefaultmethod

( )f1gUnitUnit = True

( )fa+bg(Inlx1)(Inlx2) = x1 x2

( )fa+bg(Inry1)(Inr y2) = y1 y2

( )fa+bg = False

( )fabg(x1::y1)(x2::y2) = x1 x2^y1 y2

--vanilla,non-generidefaultmethod

(6 )x1 x2 = not(x1 x2):

Thisnewlassdelarationontainsanordinary,defaultde-

larationfor(6 ),justasbefore. Thenewfeatureisageneri

denition forequality,distinguishedbytheurlybraeson

theleft handside,whihenloseatype argument. Wewill

studysuhgeneridenitionsinmoredetailinSetion4.2.

Fornow,wesimplyobservethatageneridenitionworks

byindutionoverthestrutureofthetype(writteninurly

braes)atwhihthelassisinstantiated.

Nowweangiveaninstanedelarationlikethis:

instaneEqWibble

without giving ode for either method. Both methods will

be \lled in" from the lass delaration. The ordinary,

non-generidefaultmethod,(6 ),islledinverbatim. The

generidefaultmethod,( ),isspeialisedinawaywewill

desribe, to giveessentially the ode inSetion2.2. That

is,theeetoftheinstanedelarationis exatlyasifwe

hadwritten

instaneEqWibblewhere

(Wagi1) (Wagi2) = i1 i2

(Wugb1) (Wugb2) = b1 b2

w1 w2 = False

w

1 6 w

2

= not (w

1 w

2 ):

Here is another example. The lass Binary has methods

showBinandreadBinthatrespetivelyonvertavaluetoa

listofbitsandvieversa:

dataBit = 0j1

typeBin = [Bit℄

lassBinarytwhere

showBin :: t!Bin

readBin :: Bin!(t;Bin):

Arealimplementationmighthaveamoresophistiatedrep-

resentationfor Bin butthat isaseparate matter. Wean

(3)

showBinf1gUnit = [℄

showBinfa+bg(Inlx) = 0:showBinx

showBinfa+bg(Inr y) = 1:showBiny

showBinfabg(x ::y) = showBinx ++showBiny

readBinf1gbs = (Unit;bs)

readBinfa+bg[℄ = error"readBin"

readBinfa+bg(0:bs) = let(x;bs 0

)=readBinbs

in(Inlx;bs 0

)

readBinfa+bg(1:bs) = let(y;bs 0

)=readBinbs

in(Inr y;bs 0

)

readBinfabgbs = let(x;bs

1

)=readBinbs

(y;bs

2

)=readBinbs

1

in((x ::y);bs

2 ):

NotiethatreadBinproduesavalueoftheunknowntypet,

whereasshowBinand( )bothonsumesuhvalues. Again,

weanmakeWibbleaninstaneofBinarybysayingsimply

instaneBinaryWibble:

3.2 Instanes andderiving

Thoughall ofthissoundssimpleenough,ithasinteresting

andimportantonsequenes:

2 Thoughaninstane delarationforalasswithgeneri

methodsisnowratherbrief,itmuststill begiven. Itis

notthease,forexample,thatalltypesbeomeinstanes

of Eq when one gives a generi default methodin the

lassdelarationforEq.

2 Itisnotneessaryfortheinstanedelarationtoappear

inthesamemoduleasthedatatypedelaration,orthe

lassdelaration. Byontrast,inHaskell98aderiving

lause mustbe attahed to the data type delaration.

This separation is useful, beause the lass might not

evenbedenedinthesopewherethetypeisdelared.

2 Theompileronlyllsinamethoddenitionifthepro-

grammeromitsit. Forexample,ifwesaid

instaneEqWibblewhere

(Wag ) (Wag ) = True

w

2 w

2

= False;

thenthis programmer-suppliedodeis,of ourse, used.

Thisisonewayinwhihourproposaldiersfromothers.

Inmostgeneri-programmingsystems,agenerifuntion

works generiallyoveralltypes. Inourdesign, thepro-

grammer anoverride the generi denition ona type-

by-type basis.

Thisabilityisabsolutelyruialtosupportabstratdata

types. For example, asetmaybe represented asabal-

anedtreeinmorethanoneway,andequalitymusttake

aount of this fat. Simply using a generi equality

funtion would take equality of representations, whih

is simplywrong inthis ase. In asimilar way, we an

alsouseordinaryinstanedelarationstospeifywhata

generioperation shoulddoonprimitivetypes,suhas

Char,Int,Double. Inpartiular,ifyouwanttodenea

methodfor typesinvolvingfuntion-spaes, yousimply

supplyaninstanedelarationfor\!".

2 Aderivinglauseannowbeseenasshorthand(albeit

now not so muh shorter) for an instane delaration.

Thereisadierene,though. Consider

dataTreea = Nodea[Treea℄deriving(Eq):

instane(Eqa))Eq(Tree a)

Notethat inaninstane delarationwe mustexpliitly

speifythe ontext (Eq a),whihis inferred automati-

allybythederivingmehanism. Wedisussthisissue

inmoredetailinSetion4.4.

3.3 Generi representation types

Theargumentsinbraesontheleft handsideof ageneri

denitionaretypes. Theideais,ofourse,thatthesegeneri

denitions anbe speialisedfor anypartiulartype. Sup-

pose, for example,wehave adatatype List,andwemake

List aninstaneofBinary:

dataLista = Consa(List a)jNil

instane(Binarya))Binary (Lista):

Howistheompilertollinthemissingmethoddenitions?

First,wedenethegenerirepresentationtype for List,

whihwewillallList Æ

:

typeList Æ

a = (aList a)+1:

WewillhavemoretosayaboutrepresentationtypesinSe-

tion 6.2, butfor nowwe anjustthink of List Æ

as atype

that is more-or-less isomorphi to List, but one that uses

only a small, xed set of type onstrutors, namely unit,

sums,and produts. NotiealsothatList Æ

isnot a reur-

sivetype;itmentionsListontherighthandside,notList Æ

.

Soourgenerirepresentationtypesgivearepresentationfor

justthe\toplevel"ofareursivetype.

Theunit,sum,andproduttypesaredenedlikethis:

data1 = Unit

dataa+b = InlajInrb

dataab = a::b:

Of ourse, 1 is not a legal Haskell type onstrutor, and

nor are inx (+) and (). We give them speial syntax

to distinguish them from their \normal" ounterparts, (),

Either a b, and (a;b), and extendthe syntax of types to

aommodatethem.

In our example, a List is a sum (+) of two types: a

produt()oftheelement typea andaList,andtheunit

type (1). To make the isomorphism expliit, let us write

funtionsthatonverttoandfro 1

:

to-List :: 8a:List Æ

a!Lista

to-List(Inl(x::xs)) = Consx xs

to-List(InrUnit) = Nil

from-List :: 8a:List a!List Æ

a

from-List(Consx xs) = Inl(x::xs)

from-ListNil = InrUnit:

3.4 The generi instanes

Theideaisthatby regarding aList asaList Æ

, thegeneri

odeexplainswhattodo. ThegenerimethodforshowBin,

forexample,sayswhattodoiftheargumentisasum,what

todoifitisaprodut,andwhattodoifitisaunittype.

1

Inthispaperwe willmake quantiationexpliit,eventhough

Haskell98doesnotoerexpliitquantiation. So,inthisexample,

wewriteanexpliit8inthetypesignatureforto-List. Someofour

typesbeomequiteompliated,soithelpstobeabsolutelyertain

wherequantiationistakingplae.

(4)

asthreeordinaryinstanedelarations:

instaneBinary 1where

showBinUnit = [℄

readBinbs = (Unit;bs)

instane(Binarya;Binary b))Binary(a+b)where

showBin(Inl x) = 0:showBinx

showBin(Inr y) = 1:showBiny

readBin[℄ = error"readBin"

readBin(0:bs) = let(x;bs 0

)=readBin bs

in(Inlx;bs 0

)

readBin(1:bs) = let(y;bs 0

)=readBinbs

in(Inry;bs 0

)

instane(Binarya;Binary b))Binary(ab)where

showBin(x::y) = showBinx++showBiny

readBinbs = let(x;bs

1

)=readBinbs

(y;bs

2

)=readBinbs

1

in((x::y);bs

2 ):

We desribe these instane delarations for generi repre-

sentationtypesas generi instane delarations. They are

notwritten expliitly by the programmer, butinstead are

derived by the ompiler from a lass delaration that has

generidefaultmethods.Wedisussgeneriinstanedela-

rationsfurtherinSetion4.3.

3.5 Filling inthe missing methods

Weare nowready to saymore preisely howthe ompiler

llsinthe missingmethods. Inthis setion weskeththe

ideausinganexample,whileSetion6dealswiththegeneral

ase.

Whentheprogrammerwrites

instane(Binarya))Binary(Lista)

theompilerwillllinthemethoddelarationsasfollows:

showBinxs = showBin(from-Listxs)

readBinbs = asereadBinbsof

(xs;bs 0

)!(to-Listxs;bs 0

):

LetusfousonthedenitionforshowBin. Itworksintwo

stages:

1. First, from-List::8a:List a ! List Æ

a onverts the

inputlist oftypeList aintoavalueoftypeList Æ

a.

2. Seond, we all the overloaded showBin funtion to

ompletethejob,usingthemethodsofthegeneriin-

stanedelarations.

Atrstthislooksutterlybizarre. Weare deningshowBin

intermsof showBin. Butlookat thedenitiononewould

writebyhand:

instane(Binarya))Binary(List a)where

showBinNil = 0:[℄

showBin(Consxxs) = 1:showBinx++showBinxs:

The rst all is to showBin at the list element type; the

seond is a reursive allto the same showBin at the list

type.

Somethingsimilar happens withthe generi denition.

Here showBin is alled on an argument of type List Æ

a.

Thisisasumtype,sothe suminstane ofBinary kiksin

(Setion3.4). It inturn willallshowBin,oneat type 1,

and one at typea List a. The former has aninstane

makesallstoshowBinattypeaandList a.Buttheformer

isjustliketheshowBinxinthehand-writteninstane,while

thelatterisliketheshowBinxs. Soeverythingworksout.

Letusreturnbrieytotherststepabove. Intheaseof

showBin itwasfairlysimpletoonverttheargumenttoits

generirepresentationtype. OntheotherhandreadBinwas

abitmoreompliatedbeauseitreturnedapair,onlyone

omponentofwhihhadto beonverted. How,ingeneral,

doestheompiler performthis onversion? Wedevote the

wholeofSetion5tothistopi. First,though,weelaborate

ontheprogrammer-visibleaspetsofourdesign.

4 Disussion and elaboration

Wehavenowskethedthebonesofourdesign. Inthisse-

tionweelaborateonsomeofthedetails.

4.1 Construtor namesand reord labels

Annoyingly, unit, sum,and produt are notquite enough.

Consider,forexample,thestandardHaskelllassShow. To

beabletogivegeneridenitionsforshowsPre,thenames

ofthe onstrutors,and theirxities,mustbemadeaes-

sible.

Tothisendweprovideanadditionalgenerirepresenta-

tiontype,oftheform of a where isavalue variable of

typeConDesr andaisatypevariable. ThetypeConDesr

isanewprimitivetypethatomprisesallonstrutornames.

To manipulateonstrutor namesthe following operations

amongothersanbeused|foranexhaustivelistsee[4℄.

dataConDesr --abstrat

dataFixity = Nox jInx IntjInxlIntjInxrInt

onName :: ConDesr!String --primitive

onArity :: ConDesr!Int --primitive

onFixity :: ConDesr!Fixity --primitive

instaneShowConDesr where

show = onName

Using onName and onArity we animplement a simple

variantofHaskell'sShowlass|forthefull-edgedversion

see[4 ℄.

lassShow twhere

show :: t!String

showsPre :: Int!t!String

showx = showsPre 0x

showsPrefa+bgd(Inlx) = showsPre dx

showsPrefa+bgd(Inr y) = showsPre dy

showsPrefof agd(Conx)

=if onArity 0thenshow

elseshowParen (d>10 )

(show ++" "++showsPre10x)

showsPrefabgd(x::y)

=showsPre dx++" "++showsPredy

Therepresentation type of a is dened bythe following

pseudo-Haskelldelaration:

newtypeofa = Cona:

Uniquelyfor Haskell, is avaluethat isarried byatype.

It is best to think of the above delaration as dening a

familyoftypes: foreahthereisatypeonstrutor\of"

of kind? ! ? with a value onstrutor \Con " of type

a !(of a). Now,whydoesthetype of a inorporate

(5)

tosupplythisinformationonthevaluelevel.Doingsowould

workfor show,butwouldfailforread:

lassRead twhere

read :: String![(t;String)℄

readfofags = [(Conx;s3)

j(s1;s2) lexs;s1 onName;

(x;s3) read s2℄:

Theimportant point isthat read produes (not onsumes)

thevalue,andyetitrequiresaesstotheonstrutorname.

Haskell allows the programmer to assign labels to the

omponentsofaonstrutor,andthese,too,are neededby

read and show. For the purpose ofpresentation, however,

wehoosetoignoreeldnames.Infat,theyanbehandled

ompletelyanalogouslytoonstrutornames.

4.2 Generilassdelarations

Ingeneral,alassdelarationonsistsofasignature,whih

speiesthetypesofthelassmethods,andanimplementa-

tionpart,whihgivesdefaultdenitionsforthelassmeth-

ods. Thetypesignaturehasthegeneralform:

lasstx)C awhere

op

1 :: Op

1 a

:::

op

n :: Op

n a:

Theimplementationpartonsistsofgeneriandnon-generi

defaultdenitions. Anon-generi denitionisanordinary

Haskelldenition

op = ::::

Ageneridenitionanbe reognisedbythe type patterns

onthe left handside, enlosed inurly braes. It hasthe

shematiform

opf1g = :::

opfa+bg = :::

opfabg = :::

opfofag = ::::

Thetypepatternsaremandatory,sothattheequationsan

be orretly grouped. For example, onsider the generi

denitionof( )givenearlier:

( )f1gUnitUnit = True

( )fa+bg(Inlx1)(Inlx2) = x1 x2

( )fa+bg(Inr y1)(Inry2) = y1 y2

( )fa+bg = False

( )fabg(x1::y1)(x2::y2) = x1 x2^y1 y2:

Withoutthetypepatternsthereisnowaytodeidewhether

theseondbutlastequationbelongstothe(+)ortothe()

ase.

Apart from the type patterns, a generi denition has

exatlytheformofanormalHaskelldenition.

Wenotethefollowing points:

2 Alassdelarationmayspeifyanarbitrarymixtureof

generiandnon-generidefault-methoddelarations. In

the ase of Eq above, ( ) is denedby indutionover

theargumenttype,while(6 )isnon-generi. Thegeneri

andnon-generimethodsmaybemutuallyreursive.

2 Classdelarationsaretheonlyplaethatgenerideni-

tionsappearinourdesign. Thereareno\free-standing"

generi denitions, just as there are no free-standing

withthishoie,butitdoesnotlimitexpressiveness,be-

auseoneanalwaysinventalasstoenapsulateanew

overloadedorgenerifuntion.)

2 At the moment, generi default delarations may only

be givenfor type lasses,that is,for lasseswhosetype

parameterrangesovertypesofkind?. Forexample,we

annotspeifyageneridefaultmethodfortheFuntor

lass:

lassFuntorf where

fmap :: (a!b)!(f a!f b):

Thisistherstextensionweplantoaddinthefuture.

2 Foramulti-parametertypelasstherewouldbemultiple

type arguments. We do notonsider this ompliation

inthispaper.

4.3 Generi instanedelarations

InSetion3.4wesaidthatthegeneridenitionsinalass

delarationare re-expressedbytheompiler as aset ofin-

stanedelarations,oneforeahgenerirepresentationtype.

Onemightask: whynotgettheprogrammertowritethese

instanedelarationsdiretly?

Our answeris stylistirather thantehnial. We want

to present generiprogramming inHaskellas ariher lan-

guage inwhihto writedefault method delarations, and

satteringthemoverseveralinstanedelarationsdoesnot

onveythatmessage. Thequestionaboutwhetherageneri-

defaultdelarationwasavailabletousewouldbeomemore

diuse,beausesomeparts,butnotothers,mightbeavail-

able. Writing thedelaration all atone, inthe lassde-

laration, seemsto bethesimplestandmostdiretthingto

do,eventhoughitdoesinvolvealittle newsyntax.

Another stylisti reason for our deision is that it is

rathereasyto onfusethe generiinstanedelarationfor,

say,produtsabwith\ordinary"instanedelarationsfor

the orresponding \ordinary"produttype (a;b). For ex-

ample,intheaseofShow,theordinaryinstanedelaration

forprodutsmightlooklikethis:

instane(Showa;Showb))Show(a;b)where

showsPre d(x;y)

="("++showsPre0x++","++showsPre0y++")" :

Beausetuplesaretypiallyshownusingdistxnotation,we

hoosetoover-ridethegeneridenition. Nevertheless,the

lassdelarationforShow willhavegivenrisetothegeneri

instanedelaration

instane(Show a;Showb))Show (ab)where

showsPred(x::y)

=showsPredx ++" "++showsPre dy:

Reall that produts ab are usedto represent theargu-

mentsofaonstrutor. Consequently,thegeneri instane

delaration speies the layout of onstrutor arguments:

theyareshownonseutivelyseparatedbyspaes.

4.4 Inferring instaneontexts

Whenalasshasgenerimethods,oneangiveaninstane

delarationwithoutprovidingtheodeforanyofthemeth-

ods. Butonestillhastoprovidetheontext fortheinstane

delaration. Forexample,oneouldnotwrite

instaneEq(List a)

(6)

(Eqa)onstraint. Insteadonemustwrite

instaneEqa)Eq(List a):

Inontrast,theexistingderivingmehanisminfersthene-

essaryinstaneontext. Theobviousquestionis: ouldthe

ompilerinfertheinstaneontextinournewsheme? For

example,wemightwrite

instane(::: ))Eq(List a)

indiatingthattheompilershouldllinthemissingontext

\(:::)". Indeed, wemightwant toallowsuhanabbrevia-

tioninany typesignature,allowing onetowrite,say,

f ::(::: ))a!a:

Theability to writesuhpartialtypesignatures, withthe

ellipsis lled in by type inferene, has been disussed on

the Haskell mailing list, and looks perfetly feasible from

atehnial standpoint. For instanedelarationsmatters

arestillfeasible,(albeitalittletrikier,involvingaxpoint

iteration)forrst-orderkindedtypes,butwebelievethatit

isinfeasibleforhigher-orderkindedtypes(seeSetion7.3).

Inanyase,thisissueisentirelyseparatefromourmain

theme,sowedonotdisussitfurther.

5 Mappingfuntions

Wehavenowpresentedthedesignasseenbytheprogram-

mer. Before we andesribe theimplementation,however,

weneedtopausetointroduebidiretionalmaps,whihare

anessentialfoundationtotheimplementation.

ReallfromSetion3.5ourgeneralplanforllinginthe

generimethodofaninstanedelaration. Supposewehave

thefollowinglassdelaration:

lassC awhere

op :: Opa:

Wewilldealonlywithsingle-parametertypelasses,butsee

Setion9. Wealso assume,for notational larity, thatthe

typeofmethodopisgivensimplybyOpa. Weanalways

introdueatypesynonymto make this so 2

. Nowsuppose

thattheprogrammerwritestheinstanedelaration

instanetx )C (T a):

wheretx isaontext,andaisasequeneoftypevariables.

Howisthe ompiler toll inthedenitionof methodop?

Following Setion3.5itanllinthus:

instanetx )C (T a) where

op = adapt-Op(op::Op(T Æ

a)):

That is, we all op at type T Æ

a, to produe a value of

type Op(T Æ

a), andthen onvertthe value toOp (T a).

The funtion adapt-Op does this impedane-mathing by

onvertingafuntionthatworksonvaluesoftypeT Æ

a to

onethatworksonT a.

adapt-Op :: 8a:Op(T Æ

a)!Op(T a)

2

Tehnially,Haskelltypesynonymsarenotpowerfulenoughto

dosuhanabbreviationforamethodlikeproperFration:

lassRealFraawhere

properFration :: (Integralb))a!(b;a):

sineitstypehasaontextatthebeginning. Butwewillpretend

thatsuhanabbreviationispossible.

thetypeofthemethod.Herearesomeexamples:

typeIna = a!String

adapt-In :: 8a:In(T Æ

a)!In(T a)

adapt-In = f !f from-T

typeOuta = String !a

adapt-Out :: 8a:Out(T Æ

a)!Out(T a)

adapt-Out = f !to-Tf

typeBotha = a!a

adapt-Both :: 8a:Both(T Æ

a)!Both (Ta)

adapt-Both = f !to-Tf from-T:

These adapt funtionsuse the funtionsto-T and from-T,

thatonvertbetweenTaandT Æ

a;theywereintroduedin

Setion3.3. Notiethatbothto-T andfrom-T are needed;

oneby itselfwillnotdo. Furthermore,whilewedene the

lass,andhenetheOptypes,one,wemaywriteinstanes

of that lass at many dierent types, T. So we want to

abstratouttheto-T andfrom-T funtionsfromtheadapt

funtions(notethata Æ

isatypevariablebelow):

adapt-Both 0

:: 8aa Æ

:(a Æ

!a)!(a!a Æ

)

!(Botha Æ

!Botha)

adapt-Both 0

tofrom = f !tof from

adapt-Both = adapt-Both 0

to-T from-T

It turns outto be onvenient to pakage up the to-T and

from-T funtionsintoanembedding-projetionpair:

dataEPaa Æ

= EPfto::a Æ

!a;from::a!a Æ

g:

HereEP a a Æ

isjustapairof funtions,onetoonvertin

onediretionandonetoonvertbak. Nowweanwrite

adapt-Both 00

:: 8aa Æ

:EPa a Æ

!(Botha Æ

!Botha)

adapt-Both 00

ep-a = f !toep-af from ep-a

onv-T :: 8a:EP(T a) (T Æ

a)

onv-T = EPfto=to-T;from=from-Tg

adapt-Both = adapt-Both 00

onv-T:

Thelaststepistomaketheadapt funtionitselfreturnan

embedding-projetionpair, ratherthanjustthe\to" fun-

tion; and at this stage we adopt the name bimap | for

\bidiretionalmapping":

bimap-Both :: 8aa Æ

:EPaa Æ

!EP(Botha)(Botha Æ

)

bimap-Bothep-a

= EPfto=f !fromep-af toep-a;

from=f !toep-af fromep-ag

adapt-Both = to(bimap-Bothonv-T):

Itis notatall obviouswhyweonstrutmappingsinboth

diretions,onlytodisardoneofthemwhenweuseit,but

it turns out to be essential when onstruting bimap for

arbitrarytypes,aswewillseeinthenextsetion.

5.1 Generating bidiretional mappingfuntions

Inthelastsetionwegeneratedbimap-Bothforapartiular

method type Both a. We also observed that appropriate

odedepends onthe struture ofthe type ofthe method,

so the million-dollar question is: how do we generate the

bidiretional mapsfor arbitrary methodtypes? We do it

simplybyindutionoverthetypeofthemethod,thus:

bimap-Op :: 8aa Æ

:EPaa Æ

!EP(Opa)(Opa Æ

)

bimap-Opep-a = bimapfOpag[a:=ep-a℄:

(7)

thought of as a meta-funtion, evaluated at ompile time,

thatreturnsaHaskellexpression. It takesasarguments: a

type(writteninurlybraes),andanenvironment%map-

pingtypevariables toexpressions. Thesyntax[a:=ep-a℄

meansanenvironmentthatbindsatoep-a.

We denebimap by indutiononthe strutureof type

expressions:

bimapfag% = %(a)

bimapf(!)g% = bimap-Arrow

bimapfTg% = bimap-T

bimapftug% = (bimapftg%)(bimapfug%)

where

bimap-Arrow :: 8aa Æ

bb Æ

:EPaa Æ

!EPbb Æ

!EP(a !b)(a Æ

!b Æ

)

bimap-Arrow ep-aep-b

= EPfto=f !toep-bf from ep-a;

from=f !fromep-bf toep-ag:

ThebimapfTgasedealswithtypeonstrutorsotherthan

(!),whihwedisussinSetion5.2. Letustakeanexam-

ple. ReallourBoth type:

typeBoth a = a!a:

Setting%=[a:=ep-a℄wehave

bimap-Bothep-a

= bimapfa!ag%

= (bimapf(!)ag%)(bimapfag%)

= ((bimap(!)%)(bimapfag%))(bimapfag%)

= bimap-Arrow ep-aep-a

= EPfto=f !toep-af fromep-ag;

from=f !fromep-af toep-a:

5.2 Mappingoverdata types

Whatifthereis adatatype involved? For exampleinthe

typeofreadBin,thereisapairintheresulttype:

typeReadBina = Bin!(a;Bin):

Ifwejusttryoururrentshemewegetstuk:

bimap-ReadBinep

= bimapfBin!(a;Bin)g%

= bimap-Arrow (bimapfBing%)(bimapf(a;Bin)g%):

Now,sineBinisnotaparameterisedtype,thereisnothing

todo,

bimap-Bin :: EPBinBin

bimap-Bin = id-EP

id-EP :: 8a:EPaa

id-EP = EPfto=x !x;from=x !xg

whereaspairsareparameterisedovertwotypes,sowemust

pushthemappingfuntionsinside:

bimap-Pair :: 8aa Æ

bb Æ

:EPaa Æ

!EPbb Æ

!EP(a;b)(a Æ

;b Æ

)

bimap-Pair ep-aep-b

= EPfto=(x Æ

;y Æ

)!(toep-ax Æ

;toep-by Æ

);

from=(x;y)!(fromep-ax;fromep-by)g:

tureofdatatypedelarations. Themappingfuntionforthe

datatype

dataTa

1 ::: a

k

= K

1 t

11 ::: t

1m1

jjK

n t

n1 ::: t

nmn

is givenbybimap-T displayedinFig. 1. Now,whatis the

type of this bidiretional map? The answeris simpleyet

mind-boggling: thetypeofbimap-T dependsonthekindof

T. Assumethat T haskind?as, for instane,Bin. Then

thebidiretionalmapsimplyhastypeEPTT(and,infat,

bimap-T =id-EP). If T has kind ? ! ?as all the Op's

have,thenbimap-T'stypeislose tothatofan\ordinary"

mappingfuntion:

bimap-T :: 8aa Æ

:EPaa Æ

!EP(T a)(Ta Æ

):

Amoreinvolvedkind,say(?!?)!(?!?),givesriseto

amoreompliatedtype:

bimap-T :: 8f f Æ

:(8bb Æ

:EPbb Æ

!EP(f b)(f Æ

b Æ

))

!(8aa Æ

:EPaa Æ

!EP(T f a)(T f Æ

a Æ

)):

Now bimap-T has a so-alled rank-2 type signature [12 ℄.

Roughlyspeaking,bimap-Ttakesbidiretionalmapstobidi-

retional maps(this iswhy thearguments ofbimap-T are

alledbimap-ai). Ingeneral,ifT haskind,thenbimap-T

hastypeBimapfgT T whereBimap is denedbyindu-

tiononthestrutureofkinds:

Bimapf?gt t Æ

= EPtt Æ

Bimapf1 !2gtt Æ

= 8aa Æ

:Bimapf1gaa Æ

!Bimapf2g(ta)(t Æ

a Æ

):

Ifhasordern,thenBimapfgisarank-ntype. Thisposes

noproblems,however, sinetheGlasgowHaskellCompiler

internallyusesavariantofthepolymorphi-alulus[17 ℄.

Wewill sayabitmoreabouthigher-orderkindedtypes

inSetion7. Forfurtherinformationonkind-indexedtypes

suhasBimap thereaderifreferredto[7 ℄.

6 Implementing generidefault methods

Now,atlast,wearereadytotakletheimplementation. We

desribe it as a Haskell soure-to-soure translation, per-

formed (at least notionally) prior totype heking. Why?

Thetypehekeralreadydoesalotofwhatwerequire.Also

weprobablyhaveabetterhanethatgeneridefaultmeth-

ods will worksmoothlywith ompliations suhas multi-

parameter type lasses [16 ℄, impliit parameters [13℄, and

funtionaldependenies[11 ℄.

The soure-to-soure translation goes as follows. For

eahdatatype delaration, T,wegeneratethefollowing:

2 ForeahonstrutorK avalueon-K oftypeConDesr

that desribes the properties of the onstrutor (Se-

tion6.1).

2 Atypesynonym,T Æ

,forT'sgenerirepresentationtype

(Setion6.2).

2 An embedding-projetion pair onv-T ::

8a:EP (T a) (T Æ

a), that onverts between T

anditsgenerirepresentationT Æ

(Setion6.3).

Foreahlassdelaration,for lassC,wegeneratethefol-

lowing (seeSetion6.4):

2 AnemaiatedlassdelarationforC,generatedsimply

byomittingthegenerially-denedmethods.

(8)

k

where

to-T (K1x11 ::: x1m

1

) = K1(to(bimapft11g%)x11) ::: (to(bimapft1m

1 g%)x1m

1 )

:::

to-T (Knxn1 ::: xnm

n

) = Kn(to(bimapftn1g%)xn1) ::: (to(bimapftnm

n g%)xnm

n )

from-T(K1x11 ::: x1m

1

) = K1(from(bimapft11g%)x11) ::: (from(bimapft1m

1 g%)x1m

1 )

:::

from-T(Knxn1 ::: xnm

n

) = Kn(from(bimapftn1g%)xn1) ::: (from (bimapftnm

n g%)xnm

n )

% = [a1:=bimap-a1;:::;ak:=bimap-ak℄

Figure1:ThebidiretionalmappingfuntionforthedatatypeT.

2 Foreahgenerimethodop::Opa inthelassdelara-

tion,abidiretionalmapbimap-Op::8aa Æ

:EPaa Æ

!

EP(Opa)(Opa Æ

)(seeSetion5).

2 Instanedelarations forC 1,C (a+b),C (ab)and

C ( of a), all obtained by seleting the eponymous

equations from the original lass delaration (see Se-

tion3.4).

Foreahinstanedelarationwegenerate(seeSetion6.5):

2 An extended instane delaration, obtained by adding

denitionsforthegenerimethodsthatarenotspeied

expliitlyintheinstanedelaration.

6.1 Construtors

Foreahonstrutor,K,inadatatypedelaration,wepro-

dueavalueoftypeConDesr thatgivesinformationabout

theonstrutor(infat,thetypeConDesrusedintheom-

pilerisslightlymoreelaborate):

dataConDesr = ConDesrfname::String;

arity::Int;

xity::Fixityg:

Asanexample,fortheList datatypewegenerate:

on-Cons;on-Nil :: ConDesr

on-Cons = ConDesr"Cons"2NoFixity

on-Nil = ConDesr"Nil"0NoFixity:

6.2 Generirepresentation types

Foreahdatatype,T,weprodueatypesynonymT Æ

,for

itsgeneri representation type. For example, for the data

type

dataLista = Cons a(Lista)jNil

wegeneratetherepresentationtype

typeList Æ

a = on-Consof(aLista)+on-Nilof1:

Ourgenerirepresentationtypeonstrutorsare justunit,

sum,produt,and \of". Inpartiular,thereisnoreur-

sion operator. Thus, we observe that List Æ

is just a non-

reursive type synonym: List (not List Æ

) appears on the

right-handside. SoList Æ

isnotareursive type;rather,it

expressesjustthetop\layer"ofaliststruture,leavingthe

original List to do the rest. But as we have seen, this is

enough: areursivefuntionjustdoesone\layer"ofreur-

sionatatime.

Thisisunusualomparedtootherapproahes. InPolyP

[8 ℄,forinstane,thereisanadditionaltypepatternfortype

reursion (at kind ? ! ?). A very signiant advantage

hereisthatthereisnoproblemwithmutually-reursivedata

types,nor withdatatypeswithmanyparameters,bothof

whih make expliit reursionoperators extremely lumsy

andhardtouseinpratie.

Our design makes do with just binary sum and prod-

ut. Algebraidata typeswithmanyonstrutors,eahof

whih has manyelds, are enoded as nestedusesof sum

andprodut. Theexatwayinwhihthenestingisdoneis

unimportanttoourmethod.Forexample:

dataColor = Red jBluejGreen

typeColor Æ

= on-Red of1

+ (on-Blueof1+on-Greenof1)

dataTreeab = Leaf ajNode(Tree ab)b(Treeab)

typeTree Æ

ab = on-Leaf ofa

+ on-Nodeof (Tree ab(bTreeab)):

OnemaywonderabouttheeÆienyoftranslatingauser-

dened data type into a generi formbefore operating on

it,espeiallyifeverythingisenodedwithonlybinarysums

andproduts. However,suÆientlyvigorousinliningmeans

thatthegeneridatarepresentationsneverexistatrun-time

(see Setion 6.6). But, in fat, we might want to explore

spae-timetrade-os, bygetting muhmore ompatode

in exhange for some datatranslation. Our designallows

thistrade-otobemadeonaase-by-asebasis.

Whether the enoding into sums and produts is done

in alinear or binary-sub-division fashion may or may not

aeteÆieny,dependingonhowvigoroustheinliningis.

6.3 Embedding-projetion pairs

ForeahdatatypeT,wealsogeneratefuntionstoonvert

between T and T Æ

. We saw the onversion funtions for

List inSetion3.3. Theproessisentirelystraightforward,

drivenbytheenoding. Forexample:

from-Color :: Color !Color Æ

from-ColorRed = Inl(Conon-Red Unit)

from-ColorBlue = Inr (Inl(Conon-BlueUnit))

from-ColorGreen = Inr (Inr(Conon-GreenUnit))

to-Color::Color Æ

!Color

to-Color(Inl(Con on-RedUnit)) = Red

to-Color(Inr (Inl(Conon-BlueUnit))) = Blue

to-Color(Inr (Inr(Conon-GreenUnit))) = Green:

Forbimapwehavetopakagethetwoonversionfuntions

intoasinglevalue:

onv-List :: 8a:EP(List a)(List Æ

a)

onv-List = EPfto=to-List;from=from-Listg

onv-Color :: EPColorColor Æ

onv-Color = EPfto=to-Color;from =from-Colorg:

(9)

For eah generi method op ::Op a ontained in a lass

delarationwegenerateabidiretionalmap

bimap-Op :: 8aa Æ

:EPaa Æ

!EP(Opa)(Opa Æ

)

thatallowsustoonvertbetweentypesandrepresentation

types(thedenitionofbimap-Op isgiveninSetion5).

Furthermore,weprodueinstanedelarations

instaneC 1

instane(C a;C b))C (a+b)

instane(C a;C b))C (ab)

instane(C a))C (ofa)

whosebodiesare lled withthe generi methods fromthe

originallassdelaration(seeSetion3.4). Ifanequationfor

atypepatternismissing, themethodoftheorresponding

instane is undened. There is, however, one important

exeptionto this rule: ifnoequationis givenfor the type

patternofaas,forexample,inthelassesEqandBinary,

we dene the generi methods of the C ( of a) instane

by:

opfofag = to(bimap-Op(on-EP))(op::Opa)

whereon-EPisgivenbythefollowingpseudo-Haskellode

(whihdenesafamilyoffuntions):

on-EP :: 8a:EPa(ofa)

on-EP = EPfto=x !Conx;

from=(Conx)!xg:

Again,weemploythebidiretionalmaptoonvertbetween

twoisomorphitypes.

6.5 Translatinginstanedelarations

AninstanedelarationfortypeT isextendedbyllingin

implementations for themethods. More speially, ifthe

methodopisnotspeiedandifitenjoysageneridefault

denition,thenthefollowing equationissupplemented:

op = to(bimap-Oponv-T)(op::OpT Æ

):

That'sit.

6.6 Inlining

It does not sound very eÆient to translate a value from

TatoT Æ

a andthentooperateonit,butwebelievethat

abitofjudiiousinlininganyieldmoreorlesstheodeone

wouldhavewrittenbyhand. Letusonsider,for example,

showBin at type List. TheshowBinList methodwill look

somethinglikethis:

showBinList :: (Binarya))Lista!Bin

showBinListxs = showBin(from-Listxs)

typeList Æ

a = (aLista)+1

from-List :: Lista!List Æ

a:

Theallto showBin isat typeList Æ

a,so the overloading

anberesolvedstatially. Assumingthatthemethodbodies

(giveninSetion3.1)areinlined, weget:

showBinListxs

= asefrom-Listxsof

Inlz !0:asezof

(x::y)!showBinx++showBiny

Inrz!1:asezofUnit![℄:

reursivedenition:

from-List(Consx xs) = Inl(x::xs)

from-ListNil = InrUnit:

IfweinlinethisdenitioninshowBinListandsimplifyusing

standardtransformations,weget

showBinListxs

= asexsof

Consx y!0:showBinx++showBiny

Nil!1:[℄;

whihisaboutasgoodasweanhopefor.

7 Higher-order kindedtypes

Funtional programmers love abstration. In Haskell we

an,for instane,abstratovertheList datatypein

dataRosea = Branha (List(Rosea))

toobtainthemoregeneraltype:

dataGRosef a = GBranh a(f (GRosef a)):

Here, the type variable\f"ranges overtype onstrutors,

rather than types. Formally, GRose has kind(? ! ?) !

?! ?. There are numerousexamplesof suhtypedeni-

tionsin[14 ,5 ℄.Alas,itisimpossibletodenemanyinstane

delarationsfor GRose inHaskellatall. Inthis setionwe

desribe theproblem and asolution. This setion is quite

independent of the rest of the paper. Thoughwe beame

aware of the issue whenworkingongeneri programming,

we propose an extensionto Haskell that is ompletely or-

thogonaltogeneriprogramming.

7.1 What's theproblem?

Consider rstdeninganinstane for Binary (Rose a)by

hand|weignorereadBinhere:

instane(Binarya))Binary (Rosea)where

showBin(Branhx ts) = showBinx++showBints:

TherstalltoshowBinontherighthandsiderequiresthat

Binary a should hold; theontext,(Binary a), takesare

ofthat. TheseondallisattypeList(Rosea). Assuming

wehaveaninstaneelsewhereoftheform

instane(Binaryt))Binary(List t)

the seond all requires Binary (Rose a), and there is an

instanedelarationforthattoo|itgivesrisetoareursive

alltoshowBin.

Butmattersarenotsosimplewhenwewanttowritean

instaneBinary(GRosef a). Wemighttry

instane(??? ))Binary(GRosef a)where

showBin(GBranhx ts) = showBinx++showBints:

The ontext (??? ) mustaount for the alls to showBin

on the right-hand side. The rst one is ne: it requires

Binary a as before. Butthelatterisbadnews: itrequires

Binary (f (GRosef a)),andweertainlyannotwrite

instane(Binarya;Binary(f (GRosef a)))

)Binary(GRosef a)where

showBin(GBranhx ts) = showBinx++showBints:

ThisisnotlegalHaskelland,evenifitwere,thetypeheker

woulddiverge. Indeed,noordinaryHaskellontextwilldo.

(10)

What we need is a way to simplify the prediate

f (GRosef a). Thetrikistotakethe\onstant"instane

delarationthatweassumedforBinary(List a)above,and

abstratoverit:

instane(Binarya;8b:(Binaryb))Binary(f b))

)Binary(GRosef a)where

showBin(GBranh xts) = showBinx++showBints:

Now, as well as (Binary a), the ontext also ontains

a polymorphi prediate. This prediate an be used to

redue the prediate Binary (f (GRose f a)) to just

Binary (GRose f a), and we have aninstanedelaration

forthat.

Viewedin operational terms, the prediate (Binary a)

ina ontext orresponds to passing a ditionary for lass

Binary. A prediate 8b:Binary b )Binary (f b) orre-

spondstopassingaditionarytransformer tothefuntion.

7.3 Derivinginstanedelarations

Ofourse, sineBinary isaderivablelassbyvirtueofthe

generi defaultdenitions, we neednot dene showBin at

all. Weansimplywrite

instane(Binarya;8b:(Binaryb))Binary (f b))

)Binary(GRosef a)

andgetjustthesameeetasbefore. Inotherwords,thede-

rivingmehanismworkshappilyfortypesofarbitrarykinds.

Hereisaplaewhereaprogrammer-writtenontextfor

theinstanedelarationisessential. Weouldnotusethe

ideaofSetion4.4towrite:

instane(::: ))Binary (GRosef a):

Theproblemisthatthereisno\mostgeneralinstanede-

laration". Toillustratethe pointonsider thefollowing in-

stanedelarationfor theabstrattypeSet:

instane(Binarya;Orda))Binary(Set a):

Notethat we additionallyrequire that a is aninstane of

Ord. Now,giventheinstanedelarationforGRose above,

weannotinferBinary (GRose SetInt)sineSet doesnot

satisfy8b:(Binaryb))Binary (Setb). Ifwerequiresuh

aninstane,wemustgeneralizetheGRose instane:

instane(Binarya;8b:(Binaryb;Ord b))Binary(f b))

)Binary(GRosef a):

Byadding further lassonstraints to f's ontext, we an

generalize the instane delarationevenmore. Sadly, this

implies that there is no \most general" instane whih

derivingouldinfer. Notethatthisproblemdoesnotrop

upforrst-orderkindedtypes.

7.4 Formalising theextension

Hereisthegrammarforgeneralizedinstanedelarations:

instanehead ::= instane(tx

1

;:::;tx

n ))C t

ontext tx ::= 8a:(tx

1

;:::;tx

n

))Ct:

Aontextoftheform8a:(tx1;:::;txn))C twithn>1

is alled apolymorphi prediate. Notethat for n =0 we

have\ordinary"Haskell98prediates.

tions

How dowe translate amethodallop::Op T? Wemust

reateaC-ditionaryforT ifopisamethodoflassC. In

thehigher-orderkindedsituation,wemayneedtoreatea

ditionarytransformer to passto op. Fortunately,itturns

outthatthenow-standardmahineryto onstruttheor-

retditionary topassaneasily beextendedto onstrut

ditionarytransformerstoo.

Ataallsitewehavetosolvethefollowingproblem: we

haveasetofassumptionsH andasinglelauseH,theditio-

nary(transformer)required,andwewanttoknowwhether

H is alogialonsequene ofH. Additionallywereturnan

expression for theditionary (transformer) for H. We use

the following notation: H `H 7!d meansthatd is adi-

tionary (transformer)expressionthatshowshowH anbe

deduedfromH.

TheassumptionsH embody:

2 Anyinstanedelarationsinsope. Forexample:

EqInt7!dit-Eq-Int

8a:Eqa)Eq(Lista)7!dit-Eq-List .

2 Information aboutsuperlasses. Forexample:

8a:Orda)Eqa7!dit-Eq-Ord:

ThissaysthatifwehaveOrd a weandedueEqa;in

onretetermswewitnessthisfatbytheseletorfun-

tion dit-Eq-Ord whih selets the Eq ditionary from

theOrd one.

2 Constraintsfromthetypesignature. Forexample,ifwe

arehekingtypesforthefuntion

f ::

H )T

f x = :::

then we putthe assumptions

H inourassumptionset,

andtrytodeduealltheditionariesthatareneededby

allsinthebodyoff.

Weuse the following inferene rules (A standsfor As-

sumption,CforConjuntion,MPforModusPonens):

(H 7!d)2H

H `H 7!d

(A)

H `H

1 7!d

1

H `H

n 7!d

n

H `(H

1

;:::;H

n )7!(d

1

;:::;d

n )

(C)

H `(8a:

H )Q)7!f H `

H%7!d

H `P7!(f d)

(MP)

where%=[a:=x℄isarenamingsubstitution(thexiarefresh

variables) and =math(Q%;P)is the resultofmathing

Q%againstP(notethatonlythevariablesinQ%arebound).

Sofar,theserulesareentirelystandard,see,forinstane,

[10 ℄. Totheseweaddonenewrule(DRstandsforDedu-

tionRule).

H;(

H%7!v)`Q%7!d

H `(8a:

H )Q)7!(v !d)

(DR)

where % = [a:=℄ is a Skolem substitution, that is, the

i are Skolemonstants. Thus,to deduethe polymorphi

prediate 8a:

H ) Q we add the body

H to the set of

(11)

ensuresthatthisderivationworksfor alla.

Thenewruleisalled Dedution Rulebeause itre-

semblesthededutiontheoremofrst-orderlogi. Itisalso

reminisentoftheusualtyping rulefor-abstrationwhile

ModusPonensorrespondstothetypingruleforapplia-

tion.Infat,thesetworulesaptureditionaryabstration

andditionaryappliation.

Here is an example of a dedution using these rules.

Later lines are dedued from earlier ones using the spei-

edrule(weabbreviateBinary byB andOrd by0).

H = fOrdInt7!d-O-I;

Binary Int7!d-B-I;

(8a:(Binarya;Orda)

)Binary(Seta))7!d-B-Sg

(4)H `0Int7!d-O-I A

(3)H `BInt7!d-B-I A

(2)H `(B Int;0Int)7!(d-B-I;d-O-I) C(3,4)

(1)H `(8a:(Ba;0a))B(Set a))7!d-B-S A

(0)H `B(Set Int)7!d-B-S(d-B-I;d-O-I) MP(1,2)

Hereisanotherexample,thistimeofahigher-orderase:

H = fBinaryInt7!d-B-I;

(8a:(Binarya))Binary (Lista))7!d-B-L;

(8f a:(Binarya;8b:(Binaryb))Binary(f b))

)Binary(GRosef a))7!d-B-Gg:

WeabbreviateH;(Binary7!v)byH 0

.

(9)H 0

`(8b:(B b))B(Listb))7!d-B-L A

(8)H 0

`B7!v A

(7)H 0

`(B;8b:(Bb))B(List b))

7!(v;d-B-L) C(8,9)

(6)H 0

`(8f a:(::: ))B(GRosef a))7!d-B-G A

(5)H 0

`B(GRoseList)7!d-B-G (v;d-B-L) MP(6,7)

(4)H `(8b:(Bb))B(GRoseListb))

7!(v!d-B-G (v;d-B-L)) DR(5)

(3)H `BInt7!d-B-I A

(2)H `(BInt;8b:(B b))B(GRoseListb))

7!(d-B-I;v !d-B-G(v;d-B-L)) C(3,4)

(1)H `(8f a:(:::))B(GRosef a))7!d-B-G A

(0)H `B(GRose(GRoseList)Int)

7!d-B-G(d-B-I;v !d-B-G(v;d-B-L))MP(1,2)

Thenewinferenerulekiksinatline(4)andintroduesa

newassumption,B7!v,thatisusedinline(8).

8 Relatedwork

This paper improveson our earlier work[4 ℄ inseveral re-

spets. First,generidenitionsnowappear solelyinlass

delarations as generi default methods. In the previous

design generi denitions and lasses were two ompeting

features. We feel that the new proposal ts better with

\the spirit of Haskell". Seond, we have spelled out the

implementation in onsiderable detail. In partiular, the

notion of generi representation typesand the onversion

betweentypesandrepresentationtypeshasbeenmadepre-

ise. Third, we have desribed a separate extension that

allows the programmer to dene instane delarations for

higher-orderkindedtypes. Theneedforthisextensionwas

notedin[4 ℄butnosolutionwasgiven.

Thoughthereisaonsiderableamountofworkongeneri

programming[18 ,3,9 ℄this isthe rstpaperweare aware

of| apartfrom PolyP [8℄ |that aimsat addinggeneri

tension oers a speial onstrut (essentially, atype ase)

for deninggenerifuntions. Theresultingdenitionsare

similar to ours (modulo notation) exept that the generi

programmermustadditionallyonsiderasesfortypeom-

position andfor typereursion. Furthermore,PolyP is re-

strited to regular data types of kind?! ?, whereasour

proposalworksforalltypesofallkinds. Thisisquiteasig-

niantadvantage. Inpartiular,ourproposaldealsgrae-

fullywithmutually-reursivedatatypesandwithdatatypes

withmany parameters,bothof whihmakeexpliitreur-

sionoperatorslumsyandhardtouseinpratie.

The DrIFTtool [19℄isa pre-proessor for Haskell that

allows the programmer to speify rules that explain how

to implement aderivinglause for lasses otherthanthe

standard lasses. The rules are speiedas Haskell fun-

tions, mapping a type representation to Haskell program

text. DrIFThasthesigniantadvantageoftehnialsim-

pliity. However, our system oers muh stronger stati

guarantees: ifageneridefaultdelarationpassesthetype

heker,thensowillanyinstanedelarationsthatuseit. In

DrIFT,arulemaytypehekne, whileproduingHaskell

text that itself will not typehek. We also believe that

our loser integration with the language design(ahieving

generi programmingby enrihing default-methoddelara-

tions)maketheprogrammer'slifeeasier.

9 Conlusions and furtherwork

This paper desribes two separate extensions to Haskell.

Therst extensionsupports generiprogrammingthrough

anewformof defaultmethoddelaration. Theseondex-

tensionallowsonetodeneinstanedelarationsforhigher-

orderkindedtypesthroughthenotionofpolymorphipredi-

ates. Thoughtheseextensionsareorthogonaltoeahother,

the seond ensures that onegets the most outof the rst

one (surely,one wants to derive instanesfor higher-order

kindedtypes).

WebelievethatourproposalstnielyintotheHaskell

language:

2 They t with the \spirit of Haskell". At rst sight,

generiprogrammingandHaskelltypelassesareinom-

petition, butwe use generi programmingto smoothly

extendthepoweroftypelasses.

2 Weareabletoexplainwhat\deriving"meansinasys-

temati way. The ad ho nature of deriving has long

beenonsideredawart,andprogrammersoftenwantto

addnew\derivable"lasses|thatis,lassesforwhih

youansay\deriving(C)". Nowtheyan.

2 Generidenitionsanbeover-riddenatpartiulartypes

byprogrammer-suppliedinstanedelarations. Thissets

our approah apart from other generi programming

shemes. Notonlyis thisusefulforprimitivetypes,but

generimethodsareofteninappliableforabstrattypes

| onsider equality on sets represented as unordered

lists,forexample.

2 There is norun-time passingor ase-analysis of types,

beyondHaskell'sexistingditionarypassing. Ofourse,

ditionary-passingisasortoftypepassing,butitalready

exists inHaskell,anditwouldbeextremelytiresometo

introdueanother,overlappingmehanism.

Norarethereanynewrequirementstoinspetthe run-

timerepresentationofavalue,afeatureofsomepropos-

als. Our proposal is a 100% ompile-timetransforma-

tion.

(12)

bletoeliminaterun-timeoverhead(seeSetion6.6).

2 Our sheme deals suessfully with onstrutor names

and labels. Wehavetoadmit, though, thatthis is one

ofthetrikierornersofthedesign.

2 We unninglyre-use Haskell's type-lass mehanism to

instantiatethegeneri methodsfor partiulartypes, by

expressingthegeneri methodsasgeneri instanede-

larations (Setion 4.3). This approah means that we

do not need to explain or implement exatly how this

odeinstantiationtakesplae(e.g. howmuhisdoneat

ompiletime). Instead we justpiggy-bakon anexist-

ingpieeofimplementationtehnology. (Thisisreallya

pointabouttheimplementation,notaboutthedesign.)

There seem to be twomain shortomings. Firstly, the

detailsofimplementingthegeneridefaultmethods(repre-

sentationtypes,bidiretionalmappingfuntions,andsoon)

areundeniablysubtle,whihisoften abadsign. Seondly,

thetehnologytodealwithonstrutorandeldlabelsdoes

nottinaselegantlyaswewouldwish.

Weareurrentlyimplementingtheproposalandwehope

tomakethenewfeaturesavailableinthenextreleaseofthe

GlasgowHaskellCompiler.

There are several diretions we plan to explore in the

future:

2 Currently,generidefaultdelarationsmaybegivenonly

fortypelasses. However,thetheory[6 ℄alsodealswith

onstrutor lasses whose type parameter range over

types ofrst-order kind. Consequently, we plan to lift

thisrestrition.

2 InHaskell98instaneheadsmusthavethegeneralform

C (T a) where a is a sequene of distint variables.

TheGlasgowHaskellCompiler,however,allowsfornon-

general instaneheads suhas C (List Char). We are

ondent that the implementation sheme for generi

methodsanbeextendedtodealwiththisextraompli-

ation.

2 Multi-parametertypelassesareonthewishlistofmany

Haskell programmers. So it would be a shame if the

generi extension failed to supportthem. Now, multi-

parameterlassesorrespondtogeneridenitionswith

multipletypearguments,whiharetheoretiallywellun-

derstood. Soweareondentthatweanalsodealwith

thisgeneralization.

Aknowledgements

Wewouldliketothankthreeanonymousrefereesformany

valuableomments. ThanksarefurthermoreduetoJeremy

GibbonsfortheHaskellequalssign.

Referenes

[1℄ RolandBakhouse,PatrikJansson,JohanJeuring,and

LambertMeertens.GeneriProgramming|AnIntro-

dution. InS.DoaitseSwierstra,PedroR.Henriques,

andJoseN.Oliveira,editors,3rdInternationalSummer

Shool on Advaned Funtional Programming, Braga,

Portugal, volume 1608 of Leture Notes in Computer

Siene,pages28{115.Springer-Verlag,Berlin, 1999.

[2℄ Rihard Bird, Oege de Moor, and Paul Hoogendijk.

Generi funtional programmingwith typesand rela-

tions. Journalof Funtional Programming,6(1):1{28,

January1996.

YellowSeriesReport92/480/18, Department ofCom-

puterSiene,UniversityofCalgary,June1992.

[4℄ Ralf Hinze. A generi programming extension for

Haskell. InErikMeijer, editor,Proeedings ofthe 3rd

HaskellWorkshop,Paris,Frane,September1999.The

proeedingsappearedas a tehnial reportof Univer-

siteitUtreht,UU-CS-1999-28.

[5℄ RalfHinze.Manufaturingdatatypes.JournalofFun-

tional Programming, Speial Issue onAlgorithmi As-

pets ofFuntionalProgramming Languages, 2001. To

appear.

[6℄ RalfHinze. Anewapproahtogenerifuntionalpro-

gramming. InThomasW.Reps,editor,Proeedings of

the27thAnnualACMSIGPLAN-SIGACTSymposium

onPriniplesofProgrammingLanguages(POPL'00),

Boston,Massahusetts,pages119{132,January2000.

[7℄ RalfHinze. Polytypivaluespossesspolykindedtypes.

In RolandBakhouse and J.N.Oliveira, editors, Pro-

eedingsoftheFifthInternationalConfereneonMath-

ematis of Program Constrution (MPC 2000), July

2000.

[8℄ PatrikJanssonandJohanJeuring. PolyP|apolytypi

programminglanguageextension.InConfereneReord

24th ACM SIGPLAN-SIGACT Symposium on Prin-

iples of Programming Languages, POPL'97, Paris,

Frane, pages470{482.ACM-Press,January1997.

[9℄ C.B.Jay,G.Belle,andE.Moggi.FuntorialML.Jour-

nal ofFuntionalProgramming,8(6):573{619, Novem-

ber1998.

[10℄ MarkP.Jones. QualiedTypes: Theory andPratie.

CambridgeUniversityPress,1994.

[11℄ MarkP.Jones. Typelasseswithfuntionaldependen-

ies. InG.Smolka,editor,Proeedingsofthe9thEuro-

peanSymposiumonProgramming,ESOP2000,Berlin,

Germany, volume1782 of Leture Notes inComputer

Siene,pages230{244.Springer-Verlag,Marh2000.

[12℄ DanielLeivant. Polymorphi typeinferene. InPro.

10th Symposium on Priniples of Programming Lan-

guages,1983.

[13℄ Jerey R. Lewis, Mark B. Shields, Erik Meijer, and

JohnLaunhbury.Impliitparameters:Dynamisop-

ingwithstatitypes. InThomasW.Reps,editor,Pro-

eedingsof the27thAnnual ACMSIGPLAN-SIGACT

Symposium onPriniples of Programming Languages,

Boston,Massahusetts,pages108{118,January2000.

[14℄ Chris Okasaki. Purely Funtional Data Strutures.

CambridgeUniversityPress,1998.

[15℄ Simon Peyton Jones and John Hughes, edi-

tors. Haskell 98 | A Non-strit, Purely Fun-

tional Language, February 1999. Available from

http://www.haskell.org/defini tion /.

[16℄ Simon Peyton Jones, Mark Jones, and Erik Meijer.

Type lasses: Exploringthedesignspae. InProeed-

ingsoftheHaskellWorkshop,1997.

(13)

gramtransformation: A reportfrom thetrenhes. In

Hanne Riis Nielson, editor, Programming Languages

andSystems|ESOP'96, 6thEuropean Symposium on

Programming,Linkoping,Sweden,22{24April,volume

1058ofLeture NotesinComputerSiene, pages18{

44.Springer-Verlag,1996.

[18℄ KarlFritzRuehr. Analytial andStrutural Polymor-

phismExpressedusingPatternsoverTypes.PhDthesis,

UniversityofMihigan,1992.

[19℄ Noel Winstanley. A type-sensitive preproessor for

Haskell. InGlasgowWorkshoponFuntionalProgram-

ming,Ullapool,1997.

Références

Documents relatifs

We introduce a family of DG methods for (1.1)–(1.3) based on the coupling of a DG approximation to the Vlasov equation (transport equation) with several mixed finite element methods

We present our ways of investigating and reflecting on our practice through writing and our writings as ways of investigating our researching on teaching and learning science..

By focusing on how Segalen reworks the tropes of Népémakö and Poyul drawn from Bacot’s Le Thibet révolté and the “ciel occidental Disposé-en-Lotus” he

Hithin omponents an be dened for any R -split semisimple Lie group (see [24℄) and the only simple R -split Lie groups of Hermitian type are the sympleti groups.... Let G be a simple

The schemes are con- structed by combing a discontinuous Galerkin approximation to the Vlasov equation together with a mixed finite element method for the Poisson problem.. We

In Section 2, we remind the basics on the plain parareal in time algorithm including the current state of the art on the stability and convergence analysis of the algorithm; we use

With our data, the best estimation that can be given of how the adjacent possible is going to be known during the exploration is to measure the evolution in time t of Γ(2005, t )

Prepress, oder auch die Druck- vorstufe, beschreibt alle Prozesse vor dem eigentlichen Druck- prozess und bereitet die Daten für den Druck entsprechend auf.. Dazu gehört zum