/
StronglyTypedHeterogeneousCollectionsAugust26,2004OlegKiselyovFNMOC,M StronglyTypedHeterogeneousCollectionsAugust26,2004OlegKiselyovFNMOC,M

StronglyTypedHeterogeneousCollectionsAugust26,2004OlegKiselyovFNMOC,M - PDF document

alida-meadow
alida-meadow . @alida-meadow
Follow
372 views
Uploaded On 2016-06-11

StronglyTypedHeterogeneousCollectionsAugust26,2004OlegKiselyovFNMOC,M - PPT Presentation

AshorterversionofthispaperappearedintheproceedingsoftheACMSIGPLANHaskellWorkshop2004September222004SnowbirdUtahUSAPublishedbyACMPressThislongerversionprovidesseveralappendicesandsomeextrapara ID: 358499

AshorterversionofthispaperappearedintheproceedingsoftheACMSIGPLANHaskellWorkshop2004 September22 2004 Snowbird Utah USA PublishedbyACMPress.Thislongerver-sionprovidesseveralappendicesandsomeextrapara

Share:

Link:

Embed:

Download Presentation from below link

Download Pdf The PPT/PDF document "StronglyTypedHeterogeneousCollectionsAug..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

StronglyTypedHeterogeneousCollectionsAugust26,2004OlegKiselyovFNMOC,Monterey,CARalfL¨ammelVU&CWI,AmsterdamKeeanSchupkeImperialCollege,LondonAbstractAheterogeneouscollectionisadatatypethatiscapableofstor-ingdataofdifferenttypes,whileprovidingoperationsforlook-up,update,iteration,andothers.Therearevariouskindsofheteroge-neouscollections,differinginrepresentation,invariants,andaccessoperations.WedescribeHLIST—aHaskelllibraryforstronglytypedheterogeneouscollectionsincludingextensiblerecords.WeillustrateHLIST'sbenetsinthecontextoftype-safedatabaseac-cessinHaskell.TheHLISTlibraryreliesoncommonextensionsofHaskell98.OurexplorationraisesinterestingissuesregardingHaskell'stypesystem,inparticular,avoidanceofoverlappingin-stances,andreicationoftypeequalityandtypeunication.CategoriesandSubjectDescriptors:E.2[DataStorageRepresen-tations];D.2.13[SoftwareEngineering]:ReusableSoftware;D.3.1[ProgrammingLanguages]:FormalDenitionsandTheoryGeneralTerms:Design,Languages.Keywords:Collections,Extensiblerecords,Type-safedatabaseac-cess,Dependentlytypedprogramming,Type-indexedrows,Typeequality,Typeimprovement,Haskell.1IntroductionProgrammersintypedfunctionallanguagesareusedtohomoge-neouscollections,wherevaluesofthesametypearestoredinlists,sets,andothers.Thereexistcollectionlibraries,e.g.,EdisonforHaskell[26].Homogeneouscollectionsrelyonparametricpoly-morphism.C++programmersarealsousedtohomogeneouscol-lectionssuchasthoseintheStandardTemplateLibrary,likewiseforAdaandEiffel.Javaprogrammersareabouttoreceivesupportforparametricpolymorphism,nally.Thismayendtheuseofweaklytypedcollections(“EverythingisoftypeObject!”),whichrequirerun-timetypecastswiththepotentialofunappreciatedexceptions.Unfortunately,thenotionoftypefulhomogeneouscollectionsfailstoworkforallthescenariosthatrequirestoringvaluesofdifferenttypes.Hereisanopen-endedlistoftypicalexamplesthatcallforheterogeneouscollections:Asymboltablethatissupposedtostoreentriesofdifferenttypesisheterogeneous.Itisanitemap,wheretheresulttypedependsontheargumentvalue.AnXMLelementisheterogeneouslytyped.Infact,XMLelementsarenestedcollectionsthatareconstrainedbyregularexpressionsandthe1-ambiguityproperty. AshorterversionofthispaperappearedintheproceedingsoftheACMSIGPLANHaskellWorkshop2004,September22,2004,Snowbird,Utah,USA,PublishedbyACMPress.Thislongerver-sionprovidesseveralappendicesandsomeextraparagraphs.EachrowreturnedbyanSQLqueryisaheterogeneousmapfromcolumnnamestocells.Theresultofaqueryisahomo-geneousstreamofheterogeneousrows.Addinganadvancedobjectsystemtoafunctionallanguagerequiresheterogeneouscollectionsofakindthatcombineex-tensiblerecordswithsubtypingandanenumerationinterface.Weaklytypedencodingsarefeasibleforallthelistedscenarios.Forinstance,aheterogeneouslytypedsymboltablecanbeencodedus-ingasuitablyuniversaltype,ordynamictyping,ortype-safecast.Thepresentpaperintroducesastrongtypingdisciplineforhet-erogeneouscollections.WedeliveradedicatedHaskelllibraryHLIST,whichcoverscollectiontypessuchaslists,arrays,ex-tensiblerecords,type-indexedproductsandco-products.Tothisend,weadvancetechniquesfordependentlytypedprogramminginHaskell[12,21],andwerelyonHaskell98withcommonex-tensionsformulti-parameterclassesandfunctionaldependencies,asavailableintheGHCandHugsimplementations.(Wemanagetoavoidoverlappinginstances—intheend!)Ourdevelopmentdoesnotintroduceyetanotherlanguageextension,whichisanim-provementoverearlierproposalsforextensiblerecordsandothercollectiontypes[10,31,23,29].WeexploresomemurkywatersofHaskell'stypesystem,suchasthereicationoftypeequalityandtypeunication.Whilewehavefoundportable,soundandpracticalwaysaround,moreresearchisneededtodeliverfoundationalclar-icationsthatenablefundamentalsolutions.Weidentifytheissuesthatneedtoberesolved.Thepaperisstructuredasfollows.InSec.2,wereviewweaklytypedtechniquesfordealingwithheterogeneouscollections.InSec.3,weintroducetypefulheterogeneouslists,whichprovidethebasisfortheHLISTlibrary.Wethenworkoutdifferentkindsofaccessoperationsandcollectiontypes:Sec.4—numeral-basedaccessoperations,Sec.5—labelledcollections(orrecords),Sec.6—type-basedaccessoperations,Sec.7—type-indexedproducts.InSec.8,wedemonstratethemeritsofheterogeneouscollectionsinthecontextoftype-safedatabaseaccessinHaskell.InSec.9,wereviewourtakeonHaskell'stypesystem.InSec.10,wediscussrelatedwork,andweconcludeinSec.11.Thereareseveralappen-diceswithvariousdetails.Thesourcecodefromthepapercanberetrievedfrom[1].1 2NotsostronglytypedcollectionsWeusedatabaseprogrammingforthemotivationoftheHLISTli-braryinthispaper.WewanttogettoapointwhereSQLqueriescanberephrasedinHaskellinatypedandstructuredmanner.Asasimpleexample,letusattempttoencapsulateasimpleSQLqueryinaHaskellfunction.Thequeryshouldretrieveallanimals(theirkeysandnames)ofagivenbreedfromthe`foot-n-mouth'database.Aqueryforsheep(ratherthancows)looksasfollows:SELECTkey,nameFROMAnimalWHEREbreed='sheep';CheapstringsThefollowingHaskellcodeencodestheparameterisedquery:selectBreed::String-�SqlHandleSqlQueryResultselectBreedb=sqlQuery("SELECTkey,nameFROMAnimal"++"WHEREbreed='"++b++"'")Hereweusealow-levelODBCbindingfordatabaseaccess.ThequeryiswrappedinanSqlHandletype,whichencapsulatesanIOactionforanODBCconnection.Thequeryfunctionisparame-terisedinaStringforthebreedparameter.Thetypeofqueryresultsisdenedasfollows:typeSqlQueryResult=([ColName],[Row])typeColName=StringtypeRow=[Cell]typeCell=StringThatis,theresultofaqueryconsistsofalistofcolumnnamesandalistofrows,wherearowinturnisalistofcells.Bothcolumnnamesandcellsareplainstrings.Thisispainfulcodeintheeyeofmostprogrammers,butitisoftenacheapwaytomakethingswork.Prominentdatabaseaccesstechniquesforallkindsofprogramminglanguagesarestring-basedjustlikethat.Hand-madeuniversesIfwewantedtomaintainatleasttheprimitivedatatypesofcells,thenwecouldreplacetheuseofthestringtypewithauniverseofcelltypes(orataggedunion):dataCell=IntObjectInt|FloatObjectFloat|StringObjectString|...--andperhapsafewmorecasesArowisstillalistofsuchcells,butitiseffectivelyaheterogeneouslist.InsteadofIntandIntObjectwecanusetypesandtagsthataremoredescriptiveofthecolumns,asbelow.Clearly,suchanapplication-specicuniverseissubjecttochangewheneverthedatadictionarychanges.Thesearethetypesforthecolumnsinthe`foot-n-mouth'database:newtypeKey=KeyIntegerderiving(Show,Eq,Ord)newtypeName=NameStringderiving(Show,Eq)dataBreed=Cow|Sheepderiving(Show,Eq)newtypePrice=PriceFloatderiving(Show,Eq,Ord)dataDisease=BSE|FMderiving(Show,Eq)...WederiveShow,Eq,andOrdinstancestoallowforprintingofqueryresults,andcomparisonofcellsinWHEREconditions.WeredeneCellsuchthatitiscompleteforthe`foot-n-mouth'database.dataCell=KeyCellKey|NameCellName|BreedCellBreed|...--andcertainlymorecasesTheuniversaluniverseRatherthanintroducingproblem-specicuniversesofcelltypes,wecanemploydynamics[2,3].Haskell'slibraryData.DynamicprovidesthetypeDynamicandaninjectiontoDynaswellasapro-jectionfromDynamic.Althoughthisapproachdoesnotseemmoretyped,atleastitismoreextensible:wecanmakeeachnewuser-denedtypeamenabletoinjectionandprojectionbyprovidinganinstanceofHaskell'stypeclassTypeable.Thereisafullyequiv-alentalternative:wecanuseexistentiallyquantiedcelltypesto-getherwithanominal,extensible,type-safecast[19].Usingdynamictyping,theencodingofcolumnnamesincelltypesallowsustoleavethemoutinthetypeofqueryresults.ArowendsupbeingaheterogeneouslistofDynamics.Thatis:typeSqlQueryResult=[Row]typeRow=HListtypeHList=[Dynamic]UsinginjectionweconstructanHList-typedvalueforcowAngus:angus=[toDyn(Key42),toDyn(Name"Angus"),toDynCow,toDyn(Price75.5)]WecanprocesssuchHListswithordinarylist-processingfunc-tions,e.g.,head,tail,null,andfoldr.Wecanalsoprovidetype-basedoperations,e.g.,anoperationhOccursManytoretrieveallelementsofagiventype:1hOccursMany::Typeablea=�HList-�[a]hOccursMany=mapfromJust--unwrapJust.filterisJust--removeNothing.mapfromDynamic--getoutofDynamicForinstance,wecanattempttolookupthebreedofcowAngus:ghci-or-hugs�hOccursManyangus::[Breed][Cow]NotethatprintingHListssuchasangusrequiresextraeffort.AvalueoftypeDynamicisnormallyopaque.WecanrevisetoDyntoincludeaShowconstraintinadditiontotheTypeableconstraint.Alternatively,wecanprovideaShowinstanceforDynamic,whichattemptsfromDynamictowardsallshowabletypesthatwecanpos-siblythinkof.Thesetwooptionsaccountforweakextensibility.ToofewortoomanytypesMostprogrammersarelikelytoloathoperatingonstrings:itiscompletelyuntyped.Anon-Haskellprogrammermightregardtaggedunionsasreasonablytyped.TheHaskellprogrammerwillaskformuchmoretyping.Mostnotably,theabovetype-basedlook-upgivesnostaticguaranteethatanelementoftherelevanttypewillbefoundatrun-time.Indatabaseprogramming,theseguaranteescorrespondtostaticchecksoncolumnaccessinWHEREphrasesandelsewhere.StaticcheckswouldrequireamappingofthedatadictionarytoHaskelltypes.Forexample,wecoulddeneonenewtypeperdatabaseta-ble,witheachnewtypedescribingtablecolumnsasaproductorarecord.Wecanprocessvaluesofthesenewtypeswithgenericfunctions[19].However,wearestuck:itisnotenoughtohaveprecisetypesfordatabasetables.Wealsowouldneedprecisetypesforqueriesandtheirintermediateexpressions.Sowefacetheneedforanopen-endedsetofproductorrecordtypes.Thischallengeisaddressedbelow. 1Toavoidconfusion,weprexallheterogeneouslytypedfunc-tions,types,andclasseswithan“h”(or,an“H”)suchasinhOccursManyandHList.2 3TypefulheterogeneouslistsWeseekanotionofheterogeneousliststhatismoretypefulthan[Dynamic].Thetypeofalistshouldpreciselydescribethetypesofitselements,asatypesequenceorproduct.Thiswillallowustomakestaticpromises,e.g.,aguaranteethatalook-upoperationforatypedeliversaresult.Aswewillsee,precisionoftypingdoesnotimpairourabilitytodene`normal'list-processingfunctionality.HeterogeneouslistconstructorsWestartbydeningdatatypesforlininguptypesequences:dataHNil=HNilderiving(Eq,Show,Read)dataHConsel=HConselderiving(Eq,Show,Read)Thesedatatypesreifynormalliststructureatthetypelevel,andtherebytheyallowustostaticallydistinguishemptyandnon-emptylistsjustasindependentlytypedprogramming[12,21].Further-more,eachlistelementmayhaveadifferenttype.Forlessparentheses,weassumeright-associativeinxoperators:typee:*:l=HConsel--typelevelconstructore.*.l=HConsel--valuelevelconstructorHereisatypesequenceforanimals:typeAnimal=Key:*:Name:*:Breed:*:Price:*:HNilHereisaheterogeneouslistthatrepresentscowAngus:angus::Animal--optionaltypedeclarationangus=Key42.*.Name"Angus".*.Cow.*.Price75.5.*.HNilWenotethatheterogeneouslistsareessentiallynestedtuples.Sowecouldusethenormaltypeconstructors()and(,)insteadofHNilandHConsasin:(Key,(Name,(Breed,(Price,())))).Wefavourfreshdatatypesforbuildingheterogeneouslist.Thishelpsavoidingconfusionandclasheswith`normal'applicationsof()and(,).Wecouldalsoconsiderimplicitlyterminatedtypese-quences.Again,werequireaterminatingHNiltoavoidamess.AclassofheterogeneouslistsWhenusingHConssuchasinHConsel,wewantthetailltobeaheterogeneouslisttypeagain.Tothisend,wewillnowworkoutaclassHListwhoseextensionisthesetofallpropertypesequences,i.e.,thesetofallnested,right-associative,binaryproducts.Thisclassreplacesthetype[Dynamic]fromtheprevioussection.classHListlinstanceHListHNilinstanceHListl=�HList(HConsel)Whatisthepurposeofthisclass?SomereadersmightwonderwhetherwewanttoconstrainthetypeconstructorHConslikethat:dataHListl=�HConsel=HConselderiving...Afterduediscussionwedecided:NO,beingingoodcompany[27].Theproblemwithconstraintsondatatypesisthattheyonlyimplyaproofobligation,buttypeinferencedoesnotpropagatethemnicely.ThiswouldleadtoaproliferationofHListconstraints.WeratherplaceHListconstraintsonlist-processingfunctionalitywheneverwewantthem.AuseroftheHLISTlibrarydoesnotemploytheunconstrainedconstructorHCons,butonlyaconstrainedversionofit.Tothisend,weretype(.*.):(.*.)::HListl=�e-�l-�HConsel(.*.)=HConsList-processingoperationsFunctionsonnormallists(e.g.,head,tail,andnull)canbesys-tematicallytransposedtothetypelevel.Normally,eachtype-leveloperationissubjecttoadedicatedclass;seeApp.Aforsomeex-amples,andtheHLISTsourcedistributionforadditionalexamples.Letusconsidertherecursivefunctionforconcatenationinsomedetail.Forcomparison,werecallnormallistconcatenation:append::[a]-�[a]-�[a]append[]=idappend(x:l)=(:)x.appendlWedeneaclassHAppendforconcatenationofheterogeneouslists:classHAppendll'l''|ll'-�l''wherehAppend::l-�l'-�l''HereweuseHaskell'sextensionsformulti-parameterclassesandfunctionaldependencies—which,incidentally,wereintroducedforthesakeof`normal'collectionlibraries.Soitisnotsurpris-ingthatweendupusingtheseextensionsforheterogeneouscollec-tions.Thefunctionaldependencyll'-�l''indicatesthattheclassisatype-levelfunction—ratherthanamererelationontypes.Theinstancesfollowthedenitionofappendveryclosely:instanceHListl=�HAppendHNilllwherehAppendHNil=idinstance(HListl,HAppendll'l'')=�HAppend(HConsxl)l'(HConsxl'')wherehAppend(HConsxl)=HConsx.hAppendlWenotethatappend'sequationaltermpatternsshowuptwiceintheclassHAppend:onceintheinstanceheadsofHAppendandonceinitsmethoddenitions.Also,theinstanceconstraintsforHListareliketypecheckstobeperformedattypechecking`run-time'.Butotherwisewetranscribelistprocessingtotheheterogeneouscaseinasystematicmanner.Thereisjustaconstantfactorofnoise.Ratherthandeningallkindsofspeciclist-processingfunctions,onemightwonderifthegeneralrecursionschemesforlistprocess-ingcanalsobetranscribedtotheheterogeneoussituation.Thisisindeedthecase;seeApp.BforaheterogeneousfoldoperationandtheHLISTsourcedistributionforfurtherhigher-orderoperationsonHLists.Aside:stanamiclistsTheclassHList,andalltheclasseswithlist-processingoperations(e.g.,theshownHAppend)areinnowayrestrictedtolistsbuiltfromHNilandHCons.WecaneasilyaddinstancesforHList,HAppend,andotherssuchthatwealsodealwithlesstypefulhet-erogeneouslists(e.g.,[Dynamic]),orwithlessgenericheteroge-neouslists(suchashand-madeuniverses).Thisallowsustouseourcollectionframeworkevenincaseswhentheprecisetypesequenceforacollectionisnotknownstatically,e.g.,whencollectionsarebuiltfromuserinput.Onecanevenmixstaticallyanddynamicallytypedcollections.Anadvancedexampleofsucha“stanamically”constraineddatastructurearethebalancedtreesin[18].Fortherestofthepaperwewillfocusonstaticallytypedheterogeneouslists.4Numeral-basedaccessoperationsWewillnowdenearray-like(ornumeral-based)accessoperationsforHLists.Thatis,wewillusetype-levelnaturalstoaddresslistel-ements.TheseaccessoperationsprovideabasiclayerintheHListlibrarybecausetype-basedandlabel-basedaccessoperationscanactuallybeimplementedintermsofnumeral-basedoperations.3 classHNatn=�HLookupByHNatnle|nl-�ewherehLookupByHNat::n-�l-�eclassHNatn=�HDeleteAtHNatnll'|nl-�l'wherehDeleteAtHNat::n-�l-�l'classHNatn=�HUpdateAtHNatnell'|nel-�l'wherehUpdateAtHNat::n-�e-�l-�l'classHNatsns=�HProjectByHNatsnsll'|nsl-�l'wherehProjectByHNats::ns-�l-�l'classHNatsns=�HSplitByHNatsnsll'l''|nsl-�l'l''wherehSplitByHNats::ns-�l-�(l',l'') Figure1.Numeral-basedaccessoperationsforheterogeneouscollectionsType-levelnaturalsType-levelnaturalsarerepresentedbydatatypesforzeroandsuc-cessorfunction.Thesedatatypesaresolelyforthetype-level:theonlyvalueofthesetypesis?.2classHNatndataHZero;instanceHNatHZerodataHSuccn;instanceHNatn=�HNat(HSuccn)hZero::HZero;hZero=?hSucc::HNatn=�n-�HSuccn;hSucc_=?hPred::HNatn=�HSuccn-�n;hPred_=?Eventually,oneneedstoperformallkindsofoperationsontype-levelnaturalssuchasarithmeticsorcomparison.Asanexample,wepresent(type-level)equality,asneededelsewhereinthepaper.First,weneedtype-levelBooleans:classHBoolxdataHTrue;instanceHBoolHTruedataHFalse;instanceHBoolHFalsehTrue::HTrue;hTrue=?hFalse::HFalse;hFalse=?--classesforHAndandHOromittedHerearetheclassesforgeneraltype-levelequalityandcomparisonincludingthestraightforwardinstancesfortheequalityofnaturals:classHBoolb=�HEqxyb|xy-�bclassHBoolb=�HLtxyb|xy-�binstanceHEqHZeroHZeroHTrueinstanceHNatn=�HEqHZero(HSuccn)HFalseinstanceHNatn=�HEq(HSuccn)HZeroHFalseinstance(HNatn,HNatn',HEqnn'b)=�HEq(HSuccn)(HSuccn')b--likewiseforHLtInductionontype-levelnaturalsOnecandenevariousaccessoperationsusingnaturalsasindices;seeFig.1foranoverview.Forinstance,thedeleteoperationboilsdowntotwoinstances:oneforHZero;anotherforHSucc:instanceHDeleteAtHNatHZero(HConsel)lwherehDeleteAtHNat_(HCons_l)=linstance(HDeleteAtHNatnll',HNatn)=�HDeleteAtHNat(HSuccn)(HConsel)(HConsel')wherehDeleteAtHNatn(HConsel)=HConse(hDeleteAtHNat(hPredn)l)ExtraconstraintsFunctionalityoncollectionscarriesimpliedconstraintsduetoalltheinvolvedaccessoperations.Inaddition,onemightwanttoaddextraconstraints.Forinstance,wecanusethefollowingclasstorestrictthemaximumlengthofalist(oranarray):classHMaxLengthlsinstance(HLengthls',HLts'(HSuccs)HTrue)=�HMaxLengthls 2Wealsoprexallfakeddependentlytypedfunctionsandtypeswithan“h”(or,an“H”)suchasinhTrueandHBool.ThesetypescorrespondtosubsetsofvaluesofnormaltypessuchasInt,andsoletusdiscriminatethesubsetsofvaluesatcompiletime.class(HListl,HNatn)=�HLengthln|l-�ninstanceHLengthHNilHZeroinstance(HLengthln,HNatn,HListl)=�HLength(HConsal)(HSuccn)ByaddingHMaxLengthconstraintstosignaturesorinstances,oneinstructsHaskelltoenforcesizeboundariesatcompiletime.5ExtensiblerecordsWewillnowdenelabelledcollections,i.e.,mapsfromlabelstovalues.Inessence,wewillemploytype-levelnaturalsforlabels,butwewillenrichthestructureoflabelsforconvenienceofpro-grammingwithlabelledcollections.Weendupdeningexten-siblerecordsthisway,withoutrequiringthelanguageextensionsofearlierproposals.Fromthepointofviewofdatabaseaccess,recordsprovidetheultimateexpressivenessformappingcolumnnamestovaluesinatypefulmanner.Extensibility(andshrinkabil-ity)ofrecordsiskeytodealingwithtypesofjoinsandprojections.Haskell'snonextensiblerecordsrecalledInHaskell98,wecandenerecordtypeslikethis:dataUnpriced=Unpriced{key::Integer,name::String,breed::Breed}HereisaunpricedcowAngus:unpricedAngus=Unpriced{key=42,name="Angus",breed=Cow}WhatareaccessoperationsthatareavailableforHaskell98records?Wecanretrievecomponents,andwecanupdaterecordsinapoint-wisefashion:ghci-or-hugs�breedunpricedAngusCowghci-or-hugs�unpricedAngus{breed=Sheep}Unpriced{key=42,name="Angus",breed=Sheep}Wecannotextendsuchrecords(unlesswewerethinkingofnestingrecordsandusingpolymorphicdummyeldsforextension[6]).Also,wecannotreuselabelsamongdifferentrecordtypes,neithercanwetreatlabelsasdata;solabelsarenotrst-classcitizens.AnextensiblerecorddemoWeplacerelatedlabelsinanamespacemodelledbyasillydatatype:dataFootNMouth=FootNMouth--anamespaceLabelsinanamespaceareconstructedinasequencestartingwithfirstLabel,withnextLabelgeneratingthenextdistinguishedla-bel.Eachlabelisalsoannotatedwithastringforthelabelname.Thesearethelabelsforanimals:key=firstLabelFootNMouth"key"name=nextLabelkey"name"breed=nextLabelname"breed"price=nextLabelbreed"price"4 WebuildtherecordfortheunpricedcowAngusasfollows:unpricedAngus=key.=.(42::Integer).*.name.=."Angus".*.breed.=.Cow.*.emptyRecordThatis,recordconstructionstartsfromemptyRecord;thelabel-valuepairsareconnectedby“.=.”;andeachlabel-valuepairisaddedbyusinganoverloadedoperation“.*.”.ExtensiblerecordsareprintedmoreorlesslikeHaskell98records:ghci-or-hugs�unpricedAngusRecord{key=42,name="Angus",breed=Cow}Weretrieveacomponentfromarecordasfollows:ghci-or-hugs�unpricedAngus.!.breedCowWecanupdatecomponentsasfollows:ghci-or-hugs�unpricedAngus.@.breed.=.SheepRecord{key=42,name="Angus",breed=Sheep}Wecanreallyextendsuchrecords:ghci-or-hugs�price.=.8.8.*.unpricedAngusRecord{price=8.8,key=42,name="Angus",breed=Cow}OnepossiblemodelofextensiblerecordsLabelscanbeimplementedbytype-levelnaturals,qualiedbyanamespace,andannotatedbyastringforthelabelname:dataHNatx=�Labelxns=LabelxnsStringfirstLabel=LabelhZeronextLabel(Labelxns_)=Label(hSuccx)nsRecordsaremapsfromlabelstovalues.Wecouldgoforhetero-geneouslistsofpairs;wecouldalsogoforpairsofheterogeneouslistsofequallength.Weabstractfromthischoiceasfollows:classHZipxyl|xy-�l,l-�xywherehZip::x-�y-�lhUnzip::l-�(x,y)ArecordisazippedlistwrappedwithinRecord:newtypeRecordr=Recordr--tobeconstrainedRecordconstructionisconstrainedasfollows:mkRecord::(HZiplsvsr,HLabelSetls)=�r-�RecordrmkRecord=RecordForinstance,theemptyrecordisdenotedasfollows:emptyRecord=mkRecord$hZipHNilHNilLabelsinarecordmustbedistinct:classHLabelSetlsinstanceHLabelSetHNilinstance(HNatn,HMember(Labelnns)lsHFalse,HLabelSetls)=�HLabelSet(HCons(Labelnns)ls)Tothisend,wedeneHEq-basedmembershiptestasfollows:classHBoolb=�HMemberelb|el-�binstanceHMembereHNilHFalseinstance(HEqee'b--compareeandheade',HMemberelb'--useoflabelintail,HOrbb'b''--type-levelOR)=�HMembere(HConse'l)b''Wealsoextendequality,whichwasalreadydenedfortype-levelnaturals,suchthatwecancomputeequalityoflabels.Hereweassumethatthelabelsinarecordareinthesamenamespace:instanceHEqxx'b--comparenaturalsinlabels=�HEq(Labelxns)(Labelx'ns)bAccessoperationsInthedemo,weencounteredaccessoperationsforlook-up,update,andextension.Therearealsooperationsforappendingrecords,fordeletionofalabelanditsvalueinarecord,forrenamingofalabelinarecord,forprojectionandsplittingofarecordaccord-ingtoalabelset.Wecanimplementtheseoperationsdirectlyontherepresentationofrecords(cf.“pairoflists”vs.“listofpairs”).Alternatively,wecanusenumeral-basedaccesscomplementedbyzippingandunzipping.Forinstance,deletion(“.-.”)canbedenedasfollows:(Recordr).-.l=Recordr'where(ls,vs)=hUnziprn=hFindlls--usesHEqonlabelsls'=hDeleteAtHNatnlsvs'=hDeleteAtHNatnvsr'=hZipls'vs'Thatis,weunziptherecord;wendtheindexnofthegivenlabellinthelistlsoflabels;wedeletethesubscriptedelementsinthelistslsandvsoflabelsandvalues;wenallyre-ziptherecord.6Type-basedaccessoperationsNumeral-basedandlabel-basedaccessisinsomesensestillvalue-based—eventhoughwehadtoreifynaturalsatthetypelevel.Wewillnowworkouttrulytype-basedaccessoperations.Fromadatabaseperspective,type-basedoperationsareusefulwhentypesaredescriptiveofcolumns.Inthatcase,thereisnoneedtoemploylabel-to-valuemappings.Asforthecodingstyle,wewillmaketransientuseofoverlappinginstances,assupportedbytheGHCandHugsimplementationsofHaskell.Welatercircumventoverlappinginstances.FilteranHListforelementsofagiventypeTheoperationhOccursManyfromSec.2isanexampleofatype-basedoperation.ThetypeofelementstobeextractedfromalistofdynamicsisspeciedbyxingtheresulttypeofhOccursMany.Wewillnowdenesuchtype-basedoperationsonHListincludingmorestronglytypedones;seeFig.2foranoverview.WededicateaclasstohOccursMany:classHOccursManyelwherehOccursMany::l-�[e]TheinstanceforHNilreturns[]:instanceHOccursManyeHNilwherehOccursMany_=[]Anotherinstancedealswithanon-emptyHListwhoseheadisofthetypeofinterest;noticethateisusedtwiceintheinstancehead:instance(HListl,HOccursManyel)=�HOccursManye(HConsel)wherehOccursMany(HConsel)=e:hOccursManylThereisyetanotherinstanceforanon-emptyHListwhoseheadisnotofthesametypeastheelementtypeinhOccurs'sresulttype:instance(HListl,HOccursManyel)=�HOccursManye(HConse'l)wherehOccursMany(HCons_l)=hOccursManylThetwoHConsinstancesareoverlapping,whiletheformerismorespecicthanthelatter,whichistherebyonlyappliedwhenthefor-merisnotapplicable,i.e.,wheneverthetypeseande'aredifferent.hOccursManyistheregular“”operationfortype-basedlook-up.ThentherearesimilaroperationshOccursMany1(i.e.,“+”),hOccursOpt(i.e.,“?”),andhOccursFst(fortherstoccurrence).TheclassHOccursanditscomplementHOccursNotrequiremorethought.Mostnotably,atype-checkedapplicationofhOccursissupposedtoassurethatthereisexactlyoneelementofthetypein5 classHOccursManyelwherehOccursMany::l-�[e]--returnasmanyoccurrencesoftypeeasthereareclassHOccursMany1elwherehOccursMany1::l-�(e,[e])--returnatleastoneoccurrencebutallagainclassHOccursOptelwherehOccursOpt::l-�Maybee--returnthefirstoccurrenceifanyclassHOccursFstelwherehOccursFst::l-�e--returnthefirstoccurrenceoutofoneoremoreclassHOccurselwherehOccurs::l-�e--establishthatthereispreciselyoneoccurrenceclassHOccursNotel--constraint-onlyclassforlackofoccurrences Figure2.Type-basedlook-upoperationsforheterogeneouscollectionsquestion.SuccessfultypecheckingofhOccursangus::Breedimpliesthatangus'sbreedisdenedunambiguously.Wewillde-velopthedenitionsofHOccursandHOccursNotindetail.DocumentingpotentialtypeerrorsAtrstsight,thereisnoHOccursinstanceforHNil,butwecanprovideone—beitforthesakeofinstructiveerrormessages.In-stanceslikethefollowingmakeclass-baseddependentlytypedpro-grammingmoremanageable:instanceFail(TypeNotFounde)=�HOccurseHNilwherehOccurs=?HereweuseavacuousclassFailwithoutinstances,whichjustimplementswhatitsnamepromises,andwealsoassumeadatatypeTypeNotFoundthatservesfornothingbutanerrormessage:classFailx--nomethods,noinstances!dataTypeNotFounde--novalues,nooperations!Henceweobtainsomewhatsuggestiveerrormessages:ghci-or-hugs�hOccurs(HConsTrueHNil)::IntNoinstancefor(Fail(TypeNotFoundInt))Sowetrytolookupavalueofatypethat'snotinthelist.Hence,iterationendsupatHNil,andTypeNotFoundisreported.Suchdoc-umentaryfailureinstancesareusedthroughouttheHListlibrary.Staticlook-upWewillnowprovidetheactualdenitionofhOccurs.Thereareagaintwooverlappinginstancesfornon-emptylists;oneforthecasethattheheadtswiththetypeofinterest,andanotherforre-cursionincasewehaven'tfoundanoccurrenceyet:instance(HListl,HOccursNotel)=�HOccurse(HConsel)wherehOccurs(HConse_)=einstance(HListl,HOccursel)=�HOccurse(HConse'l)wherehOccurs(HCons_l)=hOccurslTheconstraintHOccursNotelintherstinstanceassuresthatnoelementsoftypeeoccurinthetaill.TheclassHOccursNotisforconstrainingonlyratherthanactuallook-up.Consequently,itsdenitiondoesnotcompriseanymethod:classHOccursNotel--nomethods!dataTypeFounde--forafailureinstanceinstanceHOccursNoteHNilinstance(HListl,HOccursNotel)=�HOccursNote(HConse'l)instanceFail(TypeFounde)=�HOccursNote(HConsel)Theinstancesfoldoverltotestthateachtypeisdifferentfrome.Thelastinstanceleadstofailureforanoffendinghead.ThisfailureinstanceisobligatorybecausethemoregeneralinstanceforHConswouldotherwisesilentlyskipovertheoffendingoccurrence.NoticethatHaskell'sinstanceselectionissolelybasedonsyntacti-calmatching.Hence,thefailureofthemorespecicinstance(viaFail)willnotleadtoreconsiderationofthemoregeneralinstance.Fromlook-uptoprojectionWecannowreadilydeneprojectionbymappingoveralistofre-questedelementtypesusingsimplelook-upforeachelementtype;seetheHLISTsourcedistributionfortheactualcode.Forinstance,thefollowingqueryretrievesthekeyandthenameofcowAngus:ghci-or-hugs�hProjectangus::(HConsKey(HConsNameHNil))HCons(Key42)(HCons(Name"Angus")HNil)Thisoperationresemblesprojectioninthesenseofrelationalal-gebra,orinthesenseofSQL'sSELECTstatements.(ThinkofthecolumnnamesfollowingthekeywordSELECT.)Type-basedmutationoperationsWealsoneedmutationoperationssuchasthefollowing:Deletelistelementsidentiedbytheirtype.Updatelistelementsbyvaluesofthesametype.Splitalistintoaprojectedlistanditscomplement.Theupdateoperation(s)mutateatthevaluelevelonly,e.g.:--ReplacetheoccurrencesoftypeeclassHUpdateManyelwherehUpdateMany::e-�l-�lSothetype-levelprogrammingbitsoflook-upcanbeadoptedfortype-preservingupdate.Deletionrequiresfunctionaldependencies:--Deletetheoccurrencesoftypeeinl,returnl'classHDeleteManyell'|el-�l'wherehDeleteMany::...--tobecompletedSuchmutationoperationsalsomutatetypes.Withoutfunctionaldependencies,usershadtospecifytheresulttypeexplicitly,whichisimpractical.Thetroubleisthatthecombinationofoverlappinginstancesandfunctionaldependenciesleadsusintomurkywater.Wetakethisasanincentivetoidentifyanoverlapping-freeidiom.PassingontypesasproxiesLetusrstgetthetypeofhDeleteManyright.Itcouldbethisone:classHDeleteManyell'|el-�l'wherehDeleteMany::e-�l-�l'Theargumentoftypeewouldmerelydescribethetypeoftheele-mentsthatshouldbedeleted.Wemightnothaveanysuitablevaluearound(except?).Also,theabovetypeobscurestheroleoftherstargument.Sowegoforthistypeinstead:hDeleteMany::Proxye-�l-�l'Proxiesaredenedasfollow:dataProxye;proxy::Proxye;proxy=?Hence,theonlyvalueofaproxytypeisthespecicvalue?oftheconstructedproxytype—nottobeconfusedwiththevalue?ofthetypebeingproxied.Wecanreducevaluestoproxiesifneeded:toProxy::e-�Proxye;toProxy_=?Forexample,wedeletethenameofcowAngusasfollows:ghci-or-hugs�hDeleteMany(proxy::ProxyName)angusHCons(Key42)(HConsCow(HCons(Price75.5)HNil))6 Anon-solutionAdoptingthestylethatweofferedforlook-upoperations,wewouldwanttoimplementhDeleteManywithoneinstanceforHNil;oneinstancefor`deletehead';oneinstancefor`keephead':instanceHDeleteManyeHNilHNilwherehDeleteMany_HNil=HNilinstance(HListl,HDeleteManyell')=�HDeleteManye(HConsel)l'wherehDeleteManyp(HCons_l)=hDeleteManyplinstance(HListl,HDeleteManyell')=�HDeleteManye(HConse'l)(HConse'l')wherehDeleteManyp(HConse'l)=HConse'(hDeleteManypl)Alas,thetwooverlappinginstanceheadsforHConsareinnosubsti-tutionordering.(NeitherGHCnorHugscanbepersuadedtoacceptthiscode.)MovepatternsfromtheheadtoconstraintsThereisarescue.Wesimplyneedtogeneraliseoneinstanceheadsothatitbecomesmoregeneralthantheother.Then,instanceselec-tionwillbere-enabled.Wegeneralisetheheadofthelastinstance:before:HDeleteManye(HConse'l)(HConse'l')after:HDeleteManye(HConse'l)l''Butwemustmaintainthetypeequationl''equalsHConse'l'!Tothisend,weemploytypecast.WeaddaninstanceconstraintTypeCast(HConse'l')l'',andwealsocastinthemethod:instance(HListl,HDeleteManyell',TypeCast(HConse'l')l'')=�HDeleteManye(HConse'l)l''wherehDeleteManyp(HConse'l)=typeCast(HConse'(hDeleteManypl))Thereisnoshortageoftype-safecastsforHaskell[34,8,4,19].Theoneweneedhereisreallyresolvedatthetype-level.SothereisnoMaybeinvolved,sincetypeCastcannotfailatrun-time:classTypeCastxy|x-�y,y-�xwheretypeCast::x-�yThefunctionaldependenciescaptureourexpectationoftypecasttobeanisomorphismontypes(infact,theidentityfunction).WewilldiscusstheimplementationofTypeCastinSec.9.EndedupinmurkywaterThereisnorealconsensusontheoverlappinginstancemechanismassoonasfunctionaldependenciesareinvolved.OurresultfromabovetswithGHC'smodel,butHugsreportsthattheinstancesareinconsistentwiththefunctionaldependencyforHDeleteMany.Hereisasimpleexamplethatexercisesthisdisagreement:dataFooxyclassBarxy|x-�yclassZooxy|x-�yinstanceZooyr=�Bar(Fooxy)rinstanceZoozr=�Bar(Foo(Fooxy)z)rHugs'typesystemmissesthepointthatBar'ssecondparameterisstillfunctionallydependentonpartofBar'srstparameter.OverlappingbannedWegiveuponpersuadingHugs.Also,wedonotwanttodependonthedoubtfulfutureofoverlappinginstancesingeneral.Further-more,regimesforinstanceselectiondifferinwaysotherthancon-sistencycriteriaforfunctionaldependencies.Forinstance,GHC'sinstanceselectionislazy,whereasHugs'iseager.Weavoidoverlappinginstancesbyreformulatingourproblemintoacaseselectiondrivenbyatype-levelBooleandenotingacomputedtypeequality.Thepredicatefortypeequalityisprovidedasfollows:classHBoolb=�TypeEqxyb|xy-�bproxyEq::TypeEqtt'b=�Proxyt-�Proxyt'-�bproxyEq__=?Wetakeforgrantedthatwecandenetypeequality;seeSec.9.Usingtypeequality,wereplacetheoverlappinginstancesforHDeleteManybythefollowingcase-preparinginstance:instance(HListl,TypeEqee'b,HDeleteManyCasebee'll')=�HDeleteManye(HConse'l)l'wherehDeleteManyp(HConse'l)=hDeleteManyCase(proxyEqp(toProxye'))pe'lThatis,wecomputetypeequalitysothatweareabletodecidewhethertheheadneedstobedeleted.Thisdecisionisthenimple-mentedbythehelperclassHDeleteManyCasewithinstances(i.e.,branches)forthetwoBooleans:classHDeleteManyCasebee'll'|bee'l-�l'wherehDeleteManyCase::b-�Proxye-�e'-�l-�l'instanceHDeleteManyell'=�HDeleteManyCaseHTrueeell'wherehDeleteManyCase_p_l=hDeleteManyplinstanceHDeleteManyell'=�HDeleteManyCaseHFalseee'l(HConse'l')wherehDeleteManyCase_pe'l=HConse'(hDeleteManypl)Thisidiomworksequallywellforothertype-basedoperations.Type-to-naturalmappingWecanevenfactoroutcasediscriminationsfortypeequalitytobeusedinjustasinglelocation,namelyinatype-to-naturalmapping.Theremainingtype-basedaccessoperationscanthenemploythismappingcompletedbynumeral-basedaccess.Thetype-to-naturalmappingishostedbythefollowingclass:classHNatn=�HType2HNateln|el-�nTheimplementationadoptstheoverlapping-freeidiom:instance(TypeEqe'eb,HType2HNatCasebeln)=�HType2HNate(HConse'l)nclass(HBoolb,HNatn)=�HType2HNatCasebeln|bel-�ninstanceHOccursNotel=�HType2HNatCaseHTrueelHZeroinstanceHType2HNateln=�HType2HNatCaseHFalseel(HSuccn)WenotethattherstinstancecarriesaconstraintHOccursNotel.Thismakessurethatthetypeeinquestionisassociatedwithasinglenaturalasindex.Alternatively,wecouldreturnalistofaindexesforelementsoftypee.ThiswouldbenecessaryforthereconstructionofoperationslikehOccursMany.Forinstance,type-baseddeletecannowbeexpressedconciselyintermsofnumeral-baseddelete—withoutthehassleofahelperclassforcasediscriminationonBooleans:hDeletepl=hDeleteAtHNat(hType2HNatpl)lHereweinvokethetype-to-naturalmappingusingthisfunction:hType2HNat::HType2HNateln=�Proxye-�l-�nhType2HNat__=?7 Aside:typeschemasandclass-basedprogrammingThenedetailsofourheterogeneouscollectionsreecttheem-ploymentofHaskell'sclassconcept.Mostnotably,allinvolvedtypeschemasmustbesufcientlyinstantiatedtoallowforinstanceselectionwithoutcausingambiguities.Thisisjustthesameasinthecaseofshow.readwhoseapplicationtoastringcannotbeevaluatedbecausethetypeoftheintermediateresultisnotxed.Wecanstoreandlookuppolymorphicvaluesaslongastheirtypeschemasarenotneededforinstanceselection.Sonumeral-basedaccessworksneevenforarbitrarypolymorphicelements,becausetheelementtypesdonotdriveinstanceselection:ghci-or-hugs�hLookupByHNathZero(id.*.HNil)$4242Thefollowingtype-basedaccessstillworks:ghci-or-hugs�hOccursMany(id.*.HNil)::[Bool][]WenotethathOccursManycomparesitsresulttypewithallelementtypes.Thetypeschemaforalla.a-�aofidissufcientlyinstantiatedforthat,i.e.,foralla.a-�aisdifferentfromBoolforallpossiblea.Hereisanexampleofanambiguoussituation:ghci-or-hugs�hOccursMany(?.*.HNil)::[Bool]Noinstancefor...snipped.68;敠Theinteractionofpolymorphicelementsincollectionsandclass-basedprogrammingwillcontinuetobeatopicinthenextsection.7Type-indexedproductsAsarenementoftype-basedaccesstoheterogeneouscollections,onecanevenrequirethatagivencollectionisentirelytype-indexed,i.e.,thatnotypeoccursmorethanonce.Imposingthisrequirementonlists,weobtainso-calledtype-indexedproducts(TIPs;[31]).WewillnowbrieydescribeanimplementationofTIPs.ThedualofTIPs,TICs,aredenedinApp.C.WewrapTIPsinanewtypesothatwemakethestatusofbeingtype-indexedexplicitintypesignatures.Also,wecanprovidespecialinstancesforTIPsoncewemadethistypedistinction:newtypeTIPl=TIPl--tobeconstrainedunTIP(TIPl)=lThepublicconstructorforTIPssuppliesthekeyconstraintforTIPs:mkTIP::HTypeIndexedl=.68;敠l-.68;敠TIPlmkTIP=TIPTheclassHTypeIndexedisdenedasfollows:classHListl=.68;敠HTypeIndexedlinstanceHTypeIndexedHNilinstance(HOccursNotel,HTypeIndexedl)=.68;敠HTypeIndexed(HConsel)Theinstancestraverseoverthetypesequence,andtheclassHOccursNotisemployedtoassurethatthetypeoftheheaddoesnotoccur(again)inthetail.LetusupgradeangustoaTIP:ghci-or-hugs.68;敠letmyTipyCow=TIPangusLiftingoperationsMosttrivially,thereisareplacementforHNil:emptyTIP=mkTIPHNilOperationsonTIPsareliftedasfollows.“TIP”isunwrappedinar-guments,anditiswrappedintheresult(ifthisisaTIP),whilecon-straintsareaddedsothattheHTypeIndexedpropertyisenforced.Forinstance:instance(HAppendll'l'',HTypeIndexedl'')=.68;敠HAppend(TIPl)(TIPl')(TIPl'')wherehAppend(TIPl)(TIPl')=mkTIP(hAppendll')Likewiseweoverload(.*.)toworkforTIPs,i.e.,extensionsareassuredtopreservetheTIPproperty.Toillustrateextension,welabelmyTipyCowwithBSE:ghci-or-hugs.68;敠BSE.*.myTipyCowTIP(HConsBSE...)TheanimalmyTipyCowisacow;soitcan'tbeasheepthen:ghci-or-hugs.68;敠Sheep.*.myTipyCowNoinstancefor(Fail(TypeFoundBreed))SubtypeconstraintsTIPsnaturallygiverisetoasubtypeproperty.OneTIPtypelisasubtypeofanotherTIPtypel0iflcontainsalltypesfroml0.Thisisexpressedasfollows:classSubTypell'instanceSubType(TIPl)(TIPHNil)instance(HOccursel,SubType(TIPl)(TIPl'))=.68;敠SubType(TIPl)(TIP(HConsel'))Fromthisitisclearthatwedonotcareabouttheorderofelementsinthetype-indexedproducts.WealsonotethattheintersectionofHSubTypexyandHSubTypeyximmediatelyprovidesafaithfulformoftypeequivalenceforTIPs(whilemereequalityoftheun-derlyingtypesequenceswouldnotbefaithful).Asanaside,wecanalsoinstantiatesubtypingforrecords.(ThiscanbeusedinderivinganeffectiveobjectsysteminHaskell.)Arecordtyperisasubtypeofsomerecordtyper0ifrcontainsatleastthelabelsofr0,andthecomponenttypesforthesharedlabelsarethesame.Projectionaccordingtolabelsetsisofusehere:instance(HZiplsvsr',HProjectByLabelsls(Recordr)(Recordr'))=.68;敠SubType(Recordr)(Recordr')AnidiomforconstraintannotationLetusreviewidiomaticsupportforaddingextraconstraints.Forinstance,letusdeployaconstrainedhOccursthatismeanttore-turntheKeyofananimalishTIP.TIPsthatarenotofasubtypeofTIPAnimalaretoberejected—eveniftheycarryaKey.Thiscanbeencodedasfollows:animalKey::(SubTypel(TIPAnimal)--extra,HOccursKeyl--implied)=.68;敠l-.68;敠KeyanimalKey=hOccursThetroubleisthatthisconservativeapproachforcesonetogatheralltheimpliedconstraintsandtomakethemexplicitjustastheex-traconstraints.Thereisanidiomthatallowsonetosolelyenumer-ateextraconstraints.Essentially,onedenesaconstrainedidentityfunctionthatimposestheconstraintsofinterestonitsargument.Thefollowingidentityfunctioninsistsonanimals:animalish::SubTypel(TIPAnimal)=.68;敠l-.68;敠lanimalish=idWecannowdisciplinetheKeygetterasfollows:animalKeyl=hOccurs(animalishl)::KeyThesubtypeconstrainttakesactionasonecanseehere:ghci-or-hugs.68;敠animalKeymyTipyCowKey42ghci-or-hugs.68;敠animalKey(Key42.*.emptyTIP)Noinstancesfor(Fail(TypeNotFoundPrice),Fail(TypeNotFoundBreed),Fail(TypeNotFoundName))8 TheerrormessageliststhetypesthataremissingfromAnimal.ApolymorphismbenchmarkAsproposedbyareviewerofthispaper,wewillnowconsideranexamplefrom[31],whichis,inaway,abouttype-basedmatching.Thefollowingfunctionselectstwoelementsfromacollection:tuplel=letx=hOccursll'=hDeleteAtProxy(toProxyx)ly=hOccursl'in(x,y)Thefollowingsessionshowsthatwecanmatchtheelementsofacollectioninwhateverorder,whiletheoverloadedoperationsintupleareresolvedbytheconsumersofthematchedvalues:ghci-or-hugs�letone=(1::Int)ghci-or-hugs�letincx=x+oneghci-or-hugs�letincNot(a,b)=(inca,notb)ghci-or-hugs�letnotInc(a,b)=(notb,inca)ghci-or-hugs�letoneTrue=one.*.True.*.HNilghci-or-hugs�incNot(tupleoneTrue)(2,False)ghci-or-hugs�notInc(tupleoneTrue)(False,2)Thefollowingexampleshouldarguablywork,butitdoesn't:ghci-or-hugs�inc$fst(tupleoneTrue)Noinstancesfor...snipped.68;敠Wearegoingtomakethisworkaswell!WenotethatoneTruestorestwocomponents;sobyxingthetypeofonecomponenttoInt,itshouldnotmatterthatthetypeoftheothercomponentisleftunspecied.Theproblemboilsdowntothefollowingissue:ghci-or-hugs.68;敠hOccurs(HConsTrueHNil)Noinstancefor(HOccurse(HConsBoolHNil))WewouldliketodefaultetoBoolhere.Ratherthancomparingthetypeoftheheadwithanotyetinstantiatedresulttype,thetwotypesshouldbeunied.ThehOccursoperationforTIPsdoesthis:ghci-or-hugs.68;敠hOccurs(True.*.emptyTIP)Trueghci-or-hugs.68;敠letoneTrue=one.*.True.*.emptyTIPghci-or-hugs.68;敠inc$fst(tupleoneTrue)2Eventhefollowingaddedpolymorphismishandled:ghci-or-hugs.68;敠letoneNull=one.*.[].*.emptyTIPghci-or-hugs.68;敠inc$fst(tupleoneNull)2Thekeyideaistoprovideaspecialinstanceforsingletonlists,andtoreplacethetestfortypeequalitybyunicationviatypecast:instanceTypeCaste'e=.68;敠HOccurse(TIP(HConse'HNil))wherehOccurs(TIP(HConse'_))=typeCaste'instanceHOccurse(HConsx(HConsyl))=.68;敠HOccurse(TIP(HConsx(HConsyl)))wherehOccurs(TIPl)=hOccurslThisexamplerevealsthattypecastprovidesapowerfulidiomfortypeimprovement—amorene-grainedonethanfunctionalde-pendencies.Thatis,typecastoperatesattheinstancelevelasop-posedtotheclasslevel!8DatabaseprogrammingWewillnowdemonstrateheterogeneouscollectionsfordatabaseprogramminginHaskell.Tothisend,weadoptconceptsfromLei-jenandMeijer'sembeddingapproachforSQL[20].Weemployextensiblerecordsfortwopurposes:torepresenttheresultsofqueries,andtorepresentschemasforrelationalalgebraoperations.Adetaileddiscussionoftheapproachisbeyondthescopeofthispa-per.Wenotehoweverthattheapproachscalestothefullrelationalalgebra,andtoarichsetofSQLidiomsincludingallkindsofjoins,existentialquantication,nestedqueries,andtablestatements.Werecallthesimplequeryfromthebeginningofthepaper:SELECTkey,nameFROMAnimalWHEREbreed='sheep';InHaskell,wecannowwritethisqueryinatype-safemanner.selectBreedb=--argumentbforthebreeddor1-tableanimalTabler2-restrictr1(\r-.68;䥠r.!.breed`SQL.eq`b)r3-projectr2(key.*.name.*.HNil)doSelectr3Typeinferenceworksne,buthereisthetypeofthequeryanyway:selectBreed::Breed-.68;䥠Query[Tkey:=:AnimalId:*:Tname:=:String:*:HNil]Thatis,theresultisaqueryforrecordswithtwocomponents.(ThetypesforthelabelskeyandnamearedenotedbyTkeyandTname.)TheabovedosequenceencodestheSQLqueryinfoursteps:r1:Weidentifythetableasin“FROMAnimal”.r2:WerestrictthetableaccordingtotheWHEREcondition.r3:Weperformprojectionasin“SELECTkey,name”.doSelectr3:Theactualqueryisissued.Steps1–3donotinvolveanydatabaseaccess.(Monadicstyleisusedforhygienicnamesupply.)Theoperationstable,restrict,projectcreateormodifytype-annotated,syntacticalexpressionsforrelations.Theunderlyingkeydatastructurelooksasfollows:dataRelationschema--typeannotationlayer=RelationschemaSqlRelationdataSqlRelation--expressionlayer=SqlRelation{rTag::SqlTag,rSource::SqlSource,rRestrictList::[SqlExpression],rProjectList::[SqlExpression],rGroupList::[SqlExpression],rOrderList::[SqlExpression]}Thatis,relationscarryaschema,andtheirstructuralingredientscompriseauniquetag,asource(i.e.,adatabasetable),aswellaslistsofexpressionsdescribingrestrictions(cf.WHERE),projections(includingcomputedcolumns),groupingandordering.Thetypeoftherelationalschemaforanimalsisthefollowing:typeAnimalSchema=Tkey:=:AttributeAnimalIdSqlInteger:*:Tname:=:AttributeStringSqlVarchar:*:Tbreed:=:AttributeBreedSqlVarchar:*:Tprice:=:AttributeFloatSqlNumeric:*:Tfarm:=:AttributeFarmIdSqlInteger:*:HNilTheschematypelistsboththedomainofacolumnandthecor-respondingSQLtype.Forinstance,theHaskelltypeforthekeycomponentisthenewtypeAnimalIdratherthantheSQLtypeSqlInteger.This`domainasnewtypes'techniqueincreasestypesafety:onecannotpossiblyconfuseanAnimalIdandaFarmId.WenotethatsomeofthecolumntypescouldbewrappedinMaybe,butthisisnotthecaseforAnimalSchema.ThedatatypeAttributeisaphantomtypeinitstwotypeparameters.Thesephantomsdrivecoercionsandmakeat-tributeaccesstype-safe.Forinstance,considerthesubexpression9 r.!.breed`SQL.eq`bforrestrictionintheabovequery.Thelook-upr.!.breeddoesnotjustestablishthatthereisabreedcomponent,butitalsodeliversaphantom-typedattribute,sothatitsuseinthecompoundexpressionistype-constrained.Structurally,attributeskeeptrackofsomedetailssuchasprecision,andNULLconstraints.Allsuchinformationisextractedfromthedatadictionaryofadatabase.Hereisasnippetoftheextractedtabledescriptionforanimals:animalTable::TableAnimalSchemaanimalTable=mkTable"Animal"(key.=.Attribute{...}.*.name.=.Attribute{...}.*....HNil)Thisisallwhat'sneededtomakeattributeaccesstype-safe.Re-turningtypedqueryresultsreliesonfurtherprovisions.Thatis,theactiondoSelectforexecutingaqueryhastorecastqueryresultssuchthattheyarephrasedintheHaskelltypesforcolumndomains.ThecodefortheexecutionofSELECTsmakesitallclear:doSelect(Relationschemarel)=dosqlDo(showSqlRelationrel)rows-getSqlRowsreturn$map(labelHListlabels.readHListvalues)rowswhere(labels,values)=hUnzipschemaThesubexpressionshowSqlRelationrelcomputestheSELECTstatementasastring,whichisthengiventosqlDo—thelow-level,ODBC-basedSQLhandler.Inthenextstep,wegetallthequeriedrowsasalazylistoflistsusingthisSQLservice:getSqlRows::SqlHandle[[MaybeString]]Thesubsequentmaptransformsthestring-basedrowsintotypefulonesintwosteps.Firstly,webuildanHListfromthestringswithreadHList,whileweusetheattributesfromtheschematodrivethisheterogeneouslistconstruction.Secondly,weturntheHListintoarecord,whilewereusethelabelsoftheschema.9Bychanceorbydesign?Wewillnowdiscusstheissuessurroundingthedenitionoftypeequality,inequality,andunication—andgiveimplementationsdifferinginsimplicity,genericity,andportability.WedenetheclassTypeEqxybfortypeequality.Theclassre-latestwotypesxandytothetypeHTrueincasethetwotypesareequal;otherwise,thetypesarerelatedtoHFalse.Weshouldpointouthowevergroundnessissues.IfTypeEqistoreturnHTrue,thetypesmustbeground;TypeEqcanreturnHFalseevenforun-groundtypes,providedtheyareinstantiatedenoughtodeterminethattheyarenotequal.So,TypeEqistotalforgroundtypes,andpartialforungroundtypes.WealsodenetheclassTypeCastxy:aconstraintthatholdsonlyifthetwotypesxandyareuni-able.Regardinggroundnessofxandy,theclassTypeCastislessrestrictedthanTypeEq.Thatis,TypeCastxysucceedsevenforungroundtypesxandyincasetheycanbemadeequalthroughunication.TypeEqandTypeCastarerelatedtoeachotherasfol-lows.WheneverTypeEqsucceedswithHTrue,TypeCastsucceedsaswell.WheneverTypeEqsucceedswithHFalse,TypeCastfails.Butforungroundtypes,whenTypeCastsucceeds,TypeEqmightfail.Sothetwocomplementeachotherforungroundtypes.Also,TypeEqisapartialpredicate,whileTypeCastisarelation.That'swhybothareuseful.Arepresentation-basedequalitypredicateThepredicateTypeEqxybwasintroducedinSec.6asfollows:classHBoolb=.68;敠TypeEqxyb|xy-.68;敠bWenowneedtoprovideinstancesoftheclass.Averynaiveim-plementationwouldbetoexploreallcombinationsofallpossibletypes;seetheHLISTsourcedistributionforanillustration.Albeitbeingportable(Haskell98+multi-parameterclasses),thisleadstoanimpractical,exponentialexplosioninthenumberofinstances.Amorescalableapproachistointroduceafamilyofinnitetypesfortype-leveltyperepresentations.Thatis,weassociatetypeswithtyperepresentationsviaabijection,andwemakesurethattyperep-resentationsaremoreeasilycomparedthanthetypesthemselves.Wealreadyhavealltoolsforconstructingthefamilyoftyperep-resentations:wecanassociatewitheachtypeconstructoranHNat,andassociatewitheachtypetermanHListoftherepresentationsforthetypeconstructoranditsarguments.Forinstance,using`0'forBool,`1'forInt,`2'for-.68;敠,weobtain:classTTypeableab|a-.68;敠binstanceTTypeableBool(HConsHZeroHNil)instanceTTypeableInt(HCons(HSuccHZero)HNil)instance(TTypeableaal,TTypeablebbl)=.68;敠TTypeable(a-.68;敠b)(HCons(HSucc(HSuccHZero))(HConsal(HConsblHNil)))Becausethesetyperepresentationsareconstructedinaregularwaywithever-increasingnaturals,itissufcienttoaccommodatetype-levelequalitysuchthatitcancompareheterogeneouslistsoftype-levelnaturals.Type-levelequalityfornaturalswasgiveninSec.4.HerearetheremaininginstancesforHNilandHCons:instanceHEqHNilHNilHTrueinstanceHListl=.68;敠HEqHNil(HConsel)HFalseinstanceHListl=.68;敠HEq(HConsel)HNilHFalseinstance(HListl,HListl',HEqee'b,HEqll'b',HAndbb'b'')=.68;敠HEq(HConsel)(HConse'l')b''AlltheinvolvedfunctionalitydoesnotgobeyondHaskell98andmulti-parameterclasseswithuni-directionalfunctionaldependen-cies.GHCandHugsreadilysupportthiscombination.WecannowdenetheclassTypeEq,usingthefollowinginstance:instance(TTypeablettt,TTypeablet'tt',HEqtttt'b)=.68;敠TypeEqtt'bWemakeuseofagenericinstance,whichisacommonHaskell98extension.Inturnsoutthatwehaveessentiallytransposedwhat'sknownastheData.Typeableapproach[19]tothetypelevel.Wesharethedrawbackofthisapproach:weneedtodeneaninstanceofTTypeableforeachnewtypeconstructor.Whenaddingnewin-stances,wehavetomaintainthebijectionbetweentypesandtyperepresentations.Ontheotherhand,theremainingcodeisfullygenericanddoesnotneedtobeamendedatall.AgenerictypeequalitypredicateWehaveseenthatwecanimplementTypeEqinaportableandevenpracticallyusableway,usingonlycommonlysupportedHaskellextensions.Wewouldliketointroduceafullygenericapproach,whichdoesnotneedtobeamendedwhenanewtypeconstructorisintroduced.Alas,thiselegantapproachleadsusoutofthesafehavenintounchartedwatersofexperimentalextensions.ThemostconciseimplementationreusestheoverlappingtricksthatwerediscussedinSec.6,whichmakesthesolutionGHC-specic:instanceTypeEqxxHTrueinstance(HBoolb,TypeCastHFalseb)=.68;敠TypeEqxybHerewetakeadvantageofTypeCast,whichwedenenext.10 ReicationoftypeunicationTheclassTypeCastwasintroducedinSec.6andfurtherem-ployedinSec.7.TypeCastxydiffersfromjusttypeequalityTypeEqxyHTrueasfollows.IfTypeCastxysucceeds,thenthetwotypesareunied.Thedifferencebetweenunicationandjustequalityemergeswhenthetypesarenotgrounded,i.e.,whentheycontainuninstantiatedtypevariables.Thetypes[a](e.g.,ofthepolymorphicconstant[])and[Bool]areuniable,buttheyarenotequal.TypeEqcannotestablishequalityforungroundedtypes;howeveritcanestablishdisequalityincasetheschemasaresuf-cientlyinstantiatedtodeterminethattheyarenotequal.ThemostgenericimplementationofTypeCast,whichworksforbothHugsandGHC,isasfollows:instanceTypeCastxxwheretypeCast=idForthisimplementationtowork,weneedtoimportitatahigherlevelinthemodulehierarchythanallclientsoftheclassTypeCast.Otherwise,typesimplicationwillturnconstraintsoftheformTypeCastxyintotheformTypeCastxx,andtherebyinlinetheunication.WerefertoApp.D,wherewegiveanotherimplemen-tationofTypeCast,whichdoesnotrequireseparatecompilation.Thistime,weeffectivelydelaythesimplicationstepwiththehelpoftwoauxiliaryclasses.Itseemsthatthisdelayoftypesimplica-tionisatthecoreofallattemptsattype-safecastortypeequality(e.g.,[4]).AspecicpropertyofourTypeCastisthatitallowsustocon-troltypeimprovementonaper-instancebasis,asthepolymorphismbenchmarkforTIPsshowedinSec.7.SotheutilityofTypeCastgoesstrictlybeyondagenericimplementationofTypeEq.10RelatedworkHeterogeneouslistsType-levellist-processingisarelativelyobviousopportunityoncewegetholdonfakeddependentlytypedprogramminginHaskell,aspioneeredbyHallgrenandMcBride[12,21].Forinstance,homo-geneoustype-levelvectorsareconsideredin[21].Theideaofhet-erogeneoustype-levelconstructors(whatwecallHNilandHCons)occurselsewhereintheliterature.InApp.Hof[9],Ducketal.mo-tivatetheirCHR-basedmodeloffunctionaldependenciesbyop-eratingonsuchlistsusingnumeral-basedaccess(similartoour'sinSec.4);SulzmannalsogivesarelatedimplementationintheHaskell-stylelanguageChameleon[33].In[22,23],Neubaueretal.motivateHaskellextensionsforafunctionalnotationoffunctionaldependencies,andforfunctionallogicoverloading.Theauthorsconsiderexamplesliketype-levelfunctionsappendandlength,aswellasrecord-likeoperations.Bycontrast,ourgoalwastoexplorethevariouskindsofaccessoperationsforheterogeneouscollec-tions:listprocessing,numeral-based,label-based,andtype-basedoperations.HLISTistherstheterogeneouscollectionlibrarytothebestofourknowledge.Type-indexedrowsShieldandMeijerhavestudiedthetypetheoryofextensiblerecordsandvariantsstartingfromamorebasicprinciple,namelytype-indexedrows(TIRs)[31].ATIRisnothingbutatypeexpressionthatenumeratestypes.ThisresemblesHLists,butTIRsdonotcompriseanyvalues.Sowecouldgoforconstructor-lessdatatypes:classTIRrdataEmpty;instanceTIREmptydatae:#:r;instanceTIRr=�TIR(e:#:r)ATIRiswell-formediftheenumeratedtypesaredistinct.Well-formednesscorrespondstoourHTypeIndexedconstraint.ShieldandMeijerprovidetype-leveloperatorsALLandONEthat,givenaTIR,derivetypesfortype-indexedproducts(TIPs;recallSec.7)andtype-indexedco-products(TICs;seeApp.CfortheHLISTim-plementationofTICs).WecouldredeneourdatatypesforTIPsandTICssuchthattheytakeaTIRasparameter,butthesedef-initionsandtheirusagewouldbemorecomplicatedinHaskell.ShieldandMeijerarguethat,conceptually,anewtype-likemecha-nismissufcientforlabelling.Ourdevelopmentprovideslabelsasrst-classcitizens,andwecanprovidelabelledcollectionswithoutreferencetogeneraltype-indexing(i.e.,numeralindexingissuf-cient).OurHaskell-basedreconstructionofTIPsandTICsdoesnotrequirenewlanguageextensions.ExtensiblerecordsFoundationsofextensiblerecordshavebeenstudiedintensively.SeveralHaskelllanguageextensionshavebeenproposed[10,31,29],alikeforotherlanguages,e.g.,(S)ML[6,30].TherearealsorecordcalculibyBracha,Ohoriandothers[5,24].Therearere-latedtypesystems,e.g.,forrelationalalgebra[14].WehaveshownthatwecanreconstructextensiblerecordsinHaskellstartingfromsimplernotions;inparticular:heterogeneouslistsandequalityandoftype-levelnaturals.Wecoveralltypicalrecordoperations.Wehavealsodenedsubtypingconstraintsinourframework.Labels,valuesandrecordsareallrst-classcitizensinHLIST.Sowecanwriteabstractionsthattakeandproduceentitiesofallthesekinds.Forinstance,hereisanoperationtorenamearecordlabel:hRenameLabelll'r=r''wherev=r.@.l--lookupbylabelr'=r.-.l--deleteatlabelr''=l'.=.v.*.r'--addnewlabel,oldvalueTypeequalityandtypecastInourdevelopmentofheterogeneouscollections,werelyonob-servabilityoftypeequality.Also,weemployedareiedtypeunication(`type-leveltypecast)inafewplaces.Relatedex-pressivenesshasbeenstudiedinthecontextofintensionalpoly-morphism[13],dynamictyping[2,3],anduniversalrepresenta-tions[36].SomemorerecentHaskell-biasedworkontheseno-tions[34,8,4]isnotdirectlyusableforourpurposes.Theseap-proacheseitherrequiretheprogrammertousetyperepresentations,ortheymakeaclosed-worldassumptionwithregardtothecov-eredtypes,ortheyarefocusedonsums-of-products(asopposedtotheimmediatecoverageofHaskell'snewtypesanddatatypes),ortheyinvolveexistentialquantication(whichmakesitdifculttoperformmorearbitraryoperationsonelementsinthecollec-tions).Mostnotably,werequireatypecastthatisresolvedattype-checkingtime;run-timewouldbetoolate.Haskell'stypeclassesMulti-parameterclasses[7,15,16,28]withfunctionaldependen-cies[17,9]arecrucialfortype-levelprogramminginHaskell.Thesetypingnotionsarereasonablyunderstood.Thereisanon-goingdebateifinstanceselectionshouldbeprogrammablebyus-ingconstraint-handlingrulesorfunctionallogicevaluation[32,23].Also,themerenotationforencodingtype-levelfunctionscouldper-hapsbeimproved[22].Wehaveconsideredusingoverlappingin-stancesforthedenitionofsomeaccessoperations,butultimatelyweeliminateduseofthisdebatedextensioninasystematicmanner.StaticallyenforcedinvariantsTheTIPnewtypeisanexampleofadatastructurewithastati-callycheckedinvariant(i.e.,uniqueness).Okasakiandothershaveworkedonstaticallyassuringinvariantsofcomplexdatatypes,e.g.,11 thatamatrixissquare[25].Theseexamplesnormallyrelyonclev-erlychosendataconstructors,whichmakeitimpossibletocon-struct“wrong”datastructures.Ourapproachisdifferent:typeclassesletusimposestaticconstraintsirrespectiveofdataconstruc-tors.Indeed,weusethesamedataconstructorHConstobuildhet-erogeneouslistswithandwithoutduplicates.Weexpressthecon-straintsintypes(sometimes,inphantomtypes).Ourapproachdoesnotrequireextraordinaryclevernessinthedesignofdatarepresen-tation.Furthermore,inthecaseofconstraintsencodedinphantomtypes,thereisnorun-timeor-spaceoverheadofstoringandtravers-ingchainsofdataconstructors(TIPisjustasefcientasHList).BecauseTIPisessentiallyHList,wewereabletotriviallyliftalllist-processingfunctionstoTIPs.Staticallycheckingcomplexin-variantsondatastructures,suchaswell-formednessofred-blacktreesandsize-boundariesoflists,isaknownapplicationofdepen-dentlytypedprogramming[35].Thelatterrequiresnon-trivialex-tensionstoaprogramminglanguage.Wehaveshownthatcertaininvariants,e.g.,sizeboundariesforHLists,oruniquenessinTIPs,canbestaticallyexpressedinHaskell'stypesystemalready.11ConclusionWehavesystematicallydevelopedaHaskelllibraryoverstrongly-typeddatastructuresforheterogeneouscollections—lists,arrays,extensiblerecords,andothers.Thecompositionofsuchadatastructure,e.g.,thetypesofallelements,ismanifestinitstype.Thismakesitpossibletostronglytypetheoperationsoncollections,e.g.,look-ups,updates,insertions,andprojections.Thenameofthelibrary,HLIST,emphasisesthatalldatastructuresarebuiltfromtypefulheterogeneouslists.Wehavedenedrestrictedcollections,e.g.,TIPs,constrainedbytherequirementthatnotwoelementsmayhavethesametype.Theconstraintsareagainmanifestinthetypeofthecollectionsandareenforcedbythetypechecker.TheimmediateapplicationofourHLISTlibraryisadatabaseac-cesslibrarythatcoversSQL92,returnsthequeryresultsasastreamofrecords,andstaticallychecksthatallthequeriesareconsistentwiththedatabaseschema.TheimplicationsofthelibraryHLISTturnoutfarreaching,andarestillunderactiveinvestigation.OurTIPsandrecordsareextensibleandoffersubtypingpolymorphism.Ourrecordshaverst-classla-belsthatcanbereusedacrossseveralrecordtypes.WenoticethatHLISTisimplementedinHaskellwithonlycommonextensions.HencetheHLISTlibraryaddressesthechallengeforbetterHaskellrecords,withoutbreakingexistingprograms,asarticulatedbySi-monPeytonJonesattheHaskellWorkshop2003[11].Ourrecordsalsoletusimplementhas/lacks,recordconcatenation,lengthvs.depthsubtyping.Wecannowexperimentwiththesefeaturesinrealprograms—again,withoutrequiringanylanguageextension.ExtensibleTIPsandrecordscanbethefoundationofthegen-uineobjectsystem.Thelatterofferssubtypingpolymorphism(cf.OCaml)asopposedtotheclass-boundedpolymorphismofHaskell.ItisremarkablethattypeclassesthemselveswereinstrumentalinimplementingopenTIPs.Extensiblerecordscanalsobeelabo-ratedtoprovidestronglytypedkeywordargumentswithreusablelabels.Thatis,functionargumentscanbeaddressedbykeywords,andtheseargumentscanbeoptionalormandatory.TheHLISTsourcedistributiondemonstrateskeywordarguments.DualtoTIPsareopenTICs,offeringusdynamicswithastatically-checkableconstraintonthesortoftypesencapsulatedinthedynamicenve-lope(cf.App.C).Thelists,TIPs,TICsandrecordsoftheHLISTlibrarycanalsobeemployedintypefulforeign-functioninterfacesandinXMLprocessing.OurcodereliesonthemostcommonHaskellextensions;theuseofoverlappinginstancescanbecircumvented.Infact,agenericim-plementationofthepredicateTypeEqfortypeequalitywouldstillrelyonoverlappinginasinglelocation.WecanalsoimplementTypeEqinaportablebutnon-genericmannerrelyingononein-stanceperuser-deneddatatype.OurdevelopmentsuggeststhatafundamentalsolutioncouldbetooffertypeequalityasaprimitiveinHaskell.Wehavealsoidentiedtheutilityofreiedtypeuni-cation(or`type-leveltypecast')asatoolfortypeimprovement—morene-grainedthanfunctionaldependencies.Moreresearchisneededtodeliverfoundationalclarications.AcknowledgementsWethankChung-chiehShan,MartinSulzmannandthePCoftheHaskellWorkshop2004forveryhelpfulcommentsandfeedback.12References[1]Thispaper'swebsitehttp://www.cwi.nl/ralf/HList/,2004.ThissiteprovidesanextendedpaperversionwithextraappendiciesthatcouldnotbeincludedintotheHaskellwork-shoppaper.ThissitealsoprovidesasourcecodedistributionfortheGHCandHugsimplementationsofHaskell.[2]M.Abadi,L.Cardelli,B.Pierce,andG.Plotkin.Dynamictypinginastatically-typedlanguage.In16thACMConfer-enceonPrinciplesofProgrammingLanguages,pages213–227,Jan.1989.[3]M.Abadi,L.Cardelli,B.Pierce,andD.Remy.Dynamictypinginpolymorphiclanguages.InProceedingsofthe1992ACMWorkshoponMLanditsApplications,pages92–103,SanFrancisco,June1992.[4]A.BaarsandS.Swierstra.Typingdynamictyping.InPro-ceedingsoftheseventhACMSIGPLANInternationalCon-ferenceonFunctionalProgramming,pages157–166.ACMPress,2002.[5]G.BrachaandG.Lindstrom.ModularityMeetsInheritance.InProceedings:4thInternationalConferenceonComputerLanguages,pages282–290.IEEEComputerSocietyPress,1992.[6]F.Burton.Typeextensionthroughpolymorphism.TOPLAS,12(1):135–138,1990.[7]K.Chen,P.Hudak,andM.Odersky.Parametrictypeclasses.InProceedingsofthe1992ACMConferenceonLISPandFunctionalProgramming,pages170–181.ACMPress,1992.[8]J.CheneyandR.Hinze.Alightweightimplementationofgenericsanddynamics.InProceedingsoftheACMSIGPLANWorkshoponHaskell,pages90–104.ACMPress,2002.[9]G.Duck,S.PeytonJones,P.Stuckey,andM.Sulzmann.SoundandDecidableTypeInferenceforFunctionalDepen-dencies.InD.Schmidt,editor,Proceedings,13thEuropeanSymposiumonProgramming,ESOP2004,Barcelona,Spain,March29-April2,2004,volume2986ofLNCS,pages49–63.Springer-Verlag,2004.[10]B.GasterandM.Jones.APolymorphicTypeSystemforExtensibleRecordsandVariants.TechnicalreportNOTTCS-TR-96-3,UniversityofNottingham,DepartmentofComputerScience,Nov.1996.[11]H.Nilsson.TheFutureofHaskelldiscussionattheHaskellWorkshop,2003.http://www.mail-archive.com/haskelln@haskell.org/msg13366.html.[12]T.Hallgren.Funwithfunctionaldependencies.InJointWinterMeetingoftheDepartmentsofScienceandComputerEngineering,ChalmersUniversityofTechnologyandGote-borgUniversity,Varberg,Sweden,Jan.2001,2001.http://www.cs.chalmers.se/hallgren/Papers/wm01.html.12 [13]R.HarperandG.Morrisett.Compilingpolymorphismusingintensionaltypeanalysis.In22ndACMSymposiumonPrinci-plesofProgrammingLanguages(POPL'95),pages130–141.ACMPress,Jan.1995.[14]E.W.J.VandenBussche.Polymorphictypeinferencefortherelationalalgebra.JournalofComputerandSystemSci-ences,64:694–718,2002.AnextendedabstractappearedinPODS'99.[15]M.Jones.Atheoryofqualiedtypes.InSymposiumpro-ceedingson4thEuropeansymposiumonprogramming,pages287–306.Springer-Verlag,1992.[16]M.Jones.Simplifyingandimprovingqualiedtypes.InProceedingsoftheseventhinternationalconferenceonFunc-tionalProgrammingLanguagesandComputerArchitecture,pages160–169.ACMPress,1995.[17]M.Jones.Typeclasseswithfunctionaldependencies.InPro-ceedingsofthe9thEuropeanSymposiumonProgrammingLanguagesandSystems,pages230–244.Springer-Verlag,2000.[18]O.Kiselyov.Polymorphicstanamicallybalancedbinarytrees,2003.http://www.haskell.org/pipermail/haskell/2003-April/011621.html.[19]R.L¨ammelandS.PeytonJones.Scrapyourboilerplate:apracticaldesignpatternforgenericprogramming.ACMSIG-PLANNotices,38(3):26–37,Mar.2003.Proc.oftheACMSIGPLANWorkshopTLDI2003.[20]D.LeijenandE.Meijer.Domainspecicembeddedcompil-ers.InProceedingsofthe2ndconferenceonDomain-SpecicLanguages,pages109–122.ACMPress,1999.[21]C.McBride.FakingIt(SimulatingDependentTypesinHaskell),July2002.[22]M.Neubauer,P.Thiemann,M.Gasbichler,andM.Sper-ber.AFunctionalNotationforFunctionalDependencies.InProc.2001ACMSIGPLANHaskellWorkshop,Firenze,Italy,September2001,pages101–120,2001.[23]M.Neubauer,P.Thiemann,M.Gasbichler,andM.Sperber.Functionallogicoverloading.InProceedingsofthe29thACMSIGPLAN-SIGACTsymposiumonPrinciplesofProgramminglanguages,pages233–244.ACMPress,2002.[24]A.Ohori.Apolymorphicrecordcalculusanditscompilation.ACMTOPLAS,17(6):844–895,1995.[25]C.Okasaki.Fromfastexponentiationtosquarematrices:anadventureintypes.InProceedingsofthefourthACMSIG-PLANInternationalConferenceonFunctionalProgramming,pages28–35.ACMPress,1999.[26]C.Okasaki.AnOverviewofEdison.InG.Hutton,edi-tor,ElectronicNotesinTheoreticalComputerScience,vol-ume41.Elsevier,2001.[27]S.PeytonJones.AddingOrdconstrainttoinstanceMonadSet?,2004.http://www.haskell.org/pipermail/haskell-cafe/2004-March/005998.html.[28]S.PeytonJones,M.Jones,andE.Meijer.Typeclasses:ex-ploringthedesignspace.InJ.Launchbury,editor,Haskellworkshop,Amsterdam,1997.[29]S.PeytonJonesandG.Morrisett.AproposalforrecordsinHaskell,24Feb.2003.Onlinedocument:http://research.microsoft.com/simonpj/Haskell/records.html.[30]D.Remy.Typeinferenceforrecordsinnaturalextensionofml.InTheoreticalaspectsofobject-orientedprogramming:types,semantics,andlanguagedesign,pages67–95.MITPress,1994.[31]M.ShieldsandE.Meijer.Type-indexedrows.InProceedingsofthe28thACMSIGPLAN-SIGACTsymposiumonPrinci-plesofProgrammingLanguages,pages261–275.ACMPress,2001.[32]P.StuckeyandM.Sulzmann.Atheoryofoverloading.InPro-ceedingsoftheseventhACMSIGPLANInternationalCon-ferenceonFunctionalProgramming,pages167–178.ACMPress,2002.[33]M.Sulzmannetal.Chameleon,2004.Websitehttp://www.comp.nus.edu.sg/sulzmann/chameleon/.[34]S.Weirich.Type-safecast:(functionalpearl).InProceed-ingsofthefthACMSIGPLANInternationalConferenceonFunctionalProgramming,pages58–67.ACMPress,2000.[35]H.XiandF.Pfenning.Dependenttypesinpracticalprogram-ming.InProceedingsofthe26thACMSIGPLAN-SIGACTsymposiumonPrinciplesofProgrammingLanguages,pages214–227.ACMPress,1999.[36]Z.Yang.EncodingtypesinML-Likelanguages.InM.BermanandS.Berman,editors,ProceedingsofthethirdACMSIGPLANInternationalConferenceonFunctionalPro-gramming(ICFP'98),volume34,1ofACMSIGPLANNo-tices,pages289–300,NewYork,Sept.27–291998.ACMPress.ASometriviallist-processingoperatorsWewillnowtransposeseveralnormallist-processingoperatorstotheheterogeneoussituation.TranspositionofheadandtailclassHListr=�HHeadra|r-�awherehHead::r-�ainstanceFailHListEmpty=�HHeadHNil()wherehHead_=()instanceHListr=�HHead(HConsar)awherehHead(HConsa_)=aclass(HListr,HListr')=�HTailrr'|r-�r'wherehTail::r-�r'instanceFailHListEmpty=�HTailHNilHNilwherehTail_=HNilinstanceHListr=�HTail(HConsar)rwherehTail(HCons_r)=rIntheaboveinstances,weusethesametechniqueforerrormes-sagingasexplainedinSec.6.Thatis,weemploytheFailclasstohandleinvalidapplicationsoftheoperations.Inparticular,thereisanerrormessageHListEmpty,wheneverweattempttoaccessanemptylistwhereanonemptylistisneeded.Thus,wehave:classFailx--noinstances!dataHListEmpty--nostructure!TranspositionofnullclassHBoolb=�HNulllb|l-�binstanceHNullHNilHTrueinstanceHNull(HConsel)HFalseTranspositionoflengthclassHNatn=�HLengthln|l-�ninstanceHLengthHNilHZeroinstanceHLengthln=�HLength(HConsel)(HSuccn)13 BAheterogeneouslytypedfoldoperatorWegoforthefoldoperationbecauseitistheultimateexampleofahigher-orderlist-processingfunction.WededicateaclassHFoldrtoright-associativefolding.TheHFoldrinstanceswillliftthedeningequationsforfoldrtotheclasslevel:classHListl=�HFoldrfvlr|fvl-�rwherehFoldr::f-�v-�l-�rTheinstanceforemptylistsistrivial:instanceHFoldrfvHNilvwherehFoldr_v_=vTheinstanceforHConsfollowsthenormalfoldragain,butweassumethatfunctionapplicationismodelledbyanextraclassHApply.ThisallowsustousehFoldrforfunctionsthatrequirespecicconstraintsontheinvolvedtypes:instance(HFoldrfvlr,HApplyf(e,r)r')=�HFoldrfv(HConsel)r'wherehFoldrfv(HConsel)=hApplyf(e,hFoldrfvl)TheclassHApplyresemblesfunctionapplication,indeed:classHApplyfar|fa-�rwherehApply::f-�a-�rForinstance,wecannowredenehAppendintermsofhFoldr:hAppendll'=hFoldrApplyHConsl'lThedatatypeApplyHConsstandsfor“applicationofHCons”:dataApplyHCons=ApplyHCons--aproxyforinstanceselectionThismeaningofApplyHConsisregisteredasanHApplyinstance:instanceHApplyApplyHCons(e,l)(HConsel)wherehApply_(e,l)=HConselCType-indexedco-productsWewillnowdualiseTIPstoarriveatso-calledtype-indexedsums(orco-products;TICs).ATIC-typeddatastructureholdsadatumofoneoutofaxedcollectionoftypes.Soatthevaluelevel,aTIC-typeddatastructureisnotreallyacollection,butjustonedatum.However,atthetypelevelweusealistoftypeproxiestomaintainthevalidelementtypesofaspecicTICtype,andtherebywecanrestrictconstructionanddestructionofTIC-likedatastructures.ATICdemoWerstdeneanactualTICtype,namelyonethatmodelsvariouselementtypesforcollectionsrelatedtotheanimalsinthe`foot-n-mouth'database:typeAnimalCol=Key:+:Name:+:Breed:+:Price:+:HNilHereweuse“:+:”ratherthan“:*:”topointoutthatweareinter-estedinatype-indexedco-productratherthanaproduct.WecannowconstructactualTIC-likedata.Forinstance:ghci-or-hugs�letmyCol=mkTICCow::TICAnimalColWecanalsodestructmyCol.Ifweaskforthe`right'type,thendestructionsucceedswitharesultoftheformJust...;otherwiseweobtainNothing:ghci-or-hugs�unTICmyCol::MaybeBreedJustCowghci-or-hugs�unTICmyCol::MaybePriceNothingMostnotably,TICsrestrictdestructionwithregardtostatictyping:ghci-or-hugs�unTICmyCol::MaybeStringTypeerror...SequencesoftypeproxiesWeusedthealias“:+:”abovetoenumeratethesummandsofaTICtype.Infact,“:+:”isconstructedsuchthatitlinesupproxytypesinasequence.Valuetypeswouldbemisleadingandconfusingherebecausethesequenceofsummandsismeantfornothingbutlisting`options'.Sothealiasisdenedasfollows:typee:+:l=HCons(Proxye)lTheactualpropertyofatypesequencestoconsistonlyofproxytypesiseasilyspecied.classHTypeProxiedlinstanceHTypeProxiedHNilinstanceHTypeProxiedl=�HTypeProxied(HCons(Proxye)l)TICsasconstraineddynamicsThedemosuggeststhataTICismoreconstrainedthanthetypeDynamic.Sointurn,onecandenemoreconstrainedcollectiontypesthanjust[Dynamic]orString-�Dynamic.ThereexistdifferentimplementationsofTICs,butwewillfavourhereonethatindeeddirectlyemploysHaskell'sdynamicsatthevaluelevel.ATICtypeisthenofthefollowingform:dataTICl=TICDynamic--tobeconstrainedThephantomtypeparameterlofTICenumeratestheadmittedtypesthatcanbeinjectedintothisTIC,andthatcanbesubjecttoextractionattempts.ThepublicconstructorforTICs(akainjection)listsallthenecessaryconstraints:mkTIC::(HTypeIndexedl,HTypeProxiedl,HOccurs(Proxyi)l,Typeablei)=�i-�TIClmkTICi=TIC(toDyni)TheHTypeIndexedandHTypeProxiedconstraintsrequirethatlisatype-indexedsequencesoftypeproxies.TheHOccursconstraintensuresthattheproxytypeoftheinjectedvalueiiscoveredbythesequenceofproxiesl.Finally,theTypeableconstraintallowsustouseHaskell'smoduleData.Dynamic.Itremainstodenedestruction(orprojection),whichhappenstosimplyinverttheconstrainedvalue-to-dynamicsconversion:unTIC::(HTypeIndexedl,HTypeProxiedl,HOccurs(Proxyo)l,Typeableo)=�TICl-�MaybeounTIC(TICi)=fromDynamici14 DGenerictypeunicationcont'dTheclassTypeCastwasdescribedinthesubsection'Reicationoftypeunication'ofSec.9.classTypeCastab|a-�b,b-�awheretypeCast::a-�bThatsectionshowedthemoststraightforwardimplementationofthatclass:asingleinstanceTypeCastxxwiththemethodtypeCastbeingjusttheidentity.However,thatsimpleimplemen-tationwasdifculttouse.Separatecompilationhadtobeputtouseinsometrickyway.Indeed,recallthefollowingexampleofusingTypeCastfromSec.7:instanceTypeCaste'e=�HOccurse(TIP(HConse'HNil))wherehOccurs(TIP(HConse'_))=typeCaste'WhenthecompilerseestheinstanceTypeCastxxandcombinesthatwiththefunctionaldependenciesa-�b,b-�aoftheclass,thecompilerinfersthatthetwoparametersofTypeCastmustbethesame.Thatconclusioniscorrect—thetypecastismeanttobeanisomorphismontypes(infact,theidentityfunction).Whatistrou-blesomeisthatthetypecheckerappliesthatconclusion—asatypesimplicationrule—totheHOccursinstanceaboveandinfersthatemustbee'.Thatisaproblemhowever:ifatypesignaturecon-tainsdistincttypevariables,oneshouldbeabletoinstantiatethem,atleastinprinciple,withdistincttypes.Otherwise,theinferredtypeislesspolymorphicthantheexplicitsignatureprescribes.Thisisthesamesortoferrorthatarisesinthefollowingcode:foo::a-�bfoox=xWhenprocessingtheinstancedeclarationHOccurs,thecompilereagerlyappliesthecorrecttypesimplicationrule–thetwopa-rametersofTypeCastmustbethesame–andinfersthattwotypevariableseande'mustbethesame.Theeagernesscreatestheproblem.Wewouldliketodelaythetypesimplicationuntilaf-tertheinstanceHOccurshasbeenselectedandeande'havebeeninstantiated.Inotherwords,wewouldliketounifythetypesthateande'areinstantiatedwith,ratherthanthetwotypevariablesthemselves.Tokeepthecompilerfromapplyingthetypesimplicationruletooearly,weshouldpreventtheearlyinferenceoftherulefromtheinstanceofTypeCastintherstplace.Forexample,wemaykeepthecompilerfromseeingtheinstanceTypeCastxxuntiltheveryend.Thatis,weplacethatinstanceinaseparatemoduleandimportitatahigherlevelinthemodulehierarchythanallclientsoftheclassTypeCast.ThatwastheapproachdescribedinSec.9.WewillnowgiveanotherimplementationofTypeCast,whichdoesnotrequireseparatecompilation.Iteffectivelydelaysthesimpli-cationstepwiththehelpoftwoauxiliaryclasses.Ournewimplementationmustkeepthesemanticsoftheconstraint:TypeCastabshouldholdifandonlyifthetypecorrespondingtoacanbeuniedwiththetypecorrespondingtob.Ontheotherhand,weneedtoallowforpolymorphismandpretendthatinaconstraintTypeCastab,bmaybesomethingotherthana—sotokeepthetypecheckerfromunifyingthetypevariablesainbinoccurrencesofthatconstraint.Fortunately,thetypesystemisnotverysmart:whenchoosingtheinstancesthetype-checkerlooksonlyatthesyntacticformofthetypetermsinvolved.Therefore,tofoolthetype-checkerintothinkingthatTypeCastabismorepolymorphicthanitreallyis,weintroduceaseriesofredirectionsandeventuallyarriveatthefollowingimplementation.classTypeCast'tab|ta-�b,tb-�awheretypeCast'::t-�a-�bclassTypeCast''tab|ta-�b,tb-�awheretypeCast''::t-�a-�binstanceTypeCast'()ab=�TypeCastabwheretypeCastx=typeCast'()xinstanceTypeCast''tab=�TypeCast'tabwheretypeCast'=typeCast''instanceTypeCast''()aawheretypeCast''_x=xTheauxiliaryclassesTypeCast'andTypeCast''haveanextra,dummytypeparameter,whichweinstantiateto()intheinstances.Anyothergroundtypewouldhavesufced.ThekeytosolvingthepolymorphismquandaryisthelastinstanceTypeCast''()aa.ItsigniesthatintheconstraintTypeCast''tab,bisnotneces-sarilya,becausetcanbesomethingotherthan().Semantically,though,itcanneverbeanythingbut.However,thetype-checkercannotseethatandremainssatised.Alas,thisimplementationisspecictoGHC;itdoesnotworkinHugsbecauseofthepeculiaritiesofthatsystemwithregardtomulti-parametertypeclassesandfunctionaldependencies,whichwebrieyhintedatinSec.6.Thatshowsthatmulti-parametertypeclasseswithfunctionaldependenciesarehardtogetright.WhilethiscodeworksinGHCandislogicallysound,wehavetoadmitthatweturnedthedrawbacksofthetype-checkertoouradvantage.Thisleavesasourafter-taste.Wewouldhavepreferredtorelyonasoundsemantictheoryofoverloadingratherthanonplayinggameswiththetype-checker.Hopefully,theresultsofthefoundationalworkbySulzmannandothers[32,23]willeventuallybeimplementedinallHaskellcompilers.15