4MPJones DescriptionSymbolType kindkKindtypeconstructortcTycontypevariablevTyvarxedfgenericgtypetTypeclasscClassinstanceitInstpredicatepqPreddeferredd ID: 201339
Download Pdf The PPT/PDF document "2M.P.JonesItishardforHaskellresearchers..." 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.
2M.P.JonesItishardforHaskellresearcherstoexplorenewtypesystemextensions,oreventostudyusabilityissuesthatarisewiththepresenttypesystemsuchasthesearchforbettertypeerrordiagnostics.Workintheseareasrequiresaclearunderstandingofthetypesystemand,ideally,aplatformonwhichtobuildandexperimentwithprototypeimplementations.TheexistingHaskellimplementationsarenotsuitableforthis(andwerenotintendedtobe):thenutsandboltsofatypesystemareeasilyobscuredbytheuseofcleverdatastructuresandoptimizations,orbytheneedtointegratesmoothlywithotherpartsofanimplementation.ThispaperpresentsaformaldescriptionoftheHaskelltypesystemusingtheno-tationofHaskellitselfasaspecicationlanguage.Indeed,thesourcecodeforthispaperisitselfanexecutableHaskellprogramthatispassedthroughacustompre-processorandthenthroughLATEXtoobtainthetypesetversion.ThetypecheckerisavailableinsourceformontheInternetathttp://www.cse.ogi.edu/~mpj/thih/.WehopethatthiswillserveasaresourcefortheHaskellcommunity,andthatitwillbeasignicantstepinaddressingtheproblemsdescribedpreviously.OneaudiencewhoseneedsmaynotbeparticularlywellmetbythispaperareresearchersinprogramminglanguagetypesystemswhodonothaveexperienceofHaskell.(Ofcourse,weencourageanyoneinthatpositiontolearnmoreaboutHaskell!)Indeed,wedonotfollowthetraditionalrouteinsuchsettingswherethetypesystemmightrstbepresentedinitspurestform,andthenrelatedtoamoreconcretetypeinferencealgorithmbysoundnessandcompletenesstheorems.Here,wedealonlywithtypeinference.Itdoesnotevenmakesensetoaskifouralgorithmcomputes`principal'types:suchaquestionrequiresacomparisonbetweentwodierentpresentationsofatypesystem,andweonlyhaveone.Nevertheless,webelievethatourspecicationcouldberecastinastandard,type-theoreticmannerandusedtodevelopapresentationofHaskelltypinginamoretraditionalstyle.ThecodepresentedherecanbeexecutedwithanyHaskellsystem,butourpri-marygoalshavebeenclarityandsimplicity,andtheresultingcodeisnotintendedtobeanecientimplementationoftypeinference.Indeed,insomeplaces,ourchoiceofrepresentationmayleadtosignicantoverheadsandduplicatedcomputa-tion.Itwouldbeinterestingtotrytoderiveamoreecient,butprovablycorrectimplementationfromthespecicationgivenhere.Wehavenotattemptedtodothisbecauseweexpectthatitwouldobscurethekeyideasthatwewanttoemphasize.Itthereforeremainsasatopicforfuturework,andasatesttoassesstheapplicabilityofprogramtransformationandsynthesistomodestlysizedHaskellprograms.AnothergoalofthispaperistogiveascompleteadescriptionoftheHaskelltypesystemaspossible,whilealsoaimingforconciseness.Forthistobepossible,wehaveassumedthatcertaintransformationsandcheckswillhavebeenmadepriortotypechecking,andhencethatwecanworkwithamuchsimplerabstractsyntaxthanthefullsource-levelsyntaxofHaskellwouldsuggest.Asweargueinformallyatvariouspointsinthepaper,wedonotbelievethattherewouldbeanysignicantdicultyinextendingoursystemtodealwiththemissingconstructs.Allofthefundamentalcomponents,includingthethorniestaspectsofHaskelltyping, 4M.P.Jones DescriptionSymbolType kindk;:::Kindtypeconstructortc;:::Tycontypevariablev;:::Tyvar{`xed'f;:::{`generic'g;:::typet;:::Typeclassc;:::Classinstanceit;:::Instpredicatep;q;:::Pred{`deferred'd;:::{`retained'r;:::qualiedtypeqt;:::QualTypeclassenvironmentce;:::ClassEnvschemesc;:::Schemesubstitutions;:::Substunieru;:::Substassumptiona;:::Assump identieri;:::Idliterall;:::Literalpatternpat;:::Patexpressione;f;:::Expralternativealt;:::Altbindinggroupbg;:::BindGroup Fig.1.NotationalConventionspresentationassimpleaspossible,someaspectsoftheproblemsthatwearetryingtoaddresshaveinherentcomplexityortechnicaldepththatcannotbeside-stepped.Inshort,thispaperwillprobablynotbeusefulasatutorialintroductiontoHindley-Milnerstyletypeinference!2PreliminariesForsimplicity,wepresentthecodeforourtypecheckerasasingleHaskellmodule.Theprogramusesonlyahandfulofstandardpreludefunctions,likemap,concat,all,any,mapM,etc.,andafewoperationsfromtheListandMonadlibraries:moduleTypingHaskellInHaskellwhereimportList(nub;(nn);intersect;union;partition)importMonad(msum)Forthemostpart,ourchoiceofvariablenamesfollowsthenotationalconventionssetoutinFigure1.Atrailingsonavariablenameusuallyindicatesalist.Numericsucesorprimesareusedasfurtherdecorationwherenecessary.Forexample,weusekork0forakind,andksorks0foralistofkinds.Thetypesandtermsappearing 6M.P.JonesdataTycon=TyconIdKindderivingEqThisdenitionalsoincludestypesoftheformTGenn,whichrepresent`generic'orquantiedtypevariables.TheonlyplacewhereTGenvaluesareusedisintherepresentationoftypeschemes,whichwillbedescribedinSection8.Thefollowingexamplesshowhowstandardprimitivedatatypesarerepresentedastypeconstants:tUnit=TCon(Tycon\()"Star)tChar=TCon(Tycon\Char"Star)tInt=TCon(Tycon\Int"Star)tInteger=TCon(Tycon\Integer"Star)tFloat=TCon(Tycon\Float"Star)tDouble=TCon(Tycon\Double"Star)tList=TCon(Tycon\[]"(KfunStarStar))tArrow=TCon(Tycon\(-)"(KfunStar(KfunStarStar)))tTuple2=TCon(Tycon\(,)"(KfunStar(KfunStarStar)))AfullHaskellcompilerorinterpretermightstoreadditionalinformationwitheachtypeconstant|suchasthethelistofconstructorfunctionsforanalgebraicdatatype|butsuchdetailsarenotneededduringtypechecking.MorecomplextypesarebuiltupfromconstantsandvariablesusingtheTApconstructor.Forexample,therepresentationforthetypeInt![a]isasfollows:TAp(TAptArrowtInt)(TAptList(TVar(Tyvar\a"Star)))Wedonotprovidearepresentationfortypesynonyms,assuminginsteadthattheyhavebeenfullyexpandedbeforetypechecking.Forexample,theStringtype|asynonymfor[Char]|isrepresentedas:tString::TypetString=listtCharItisalwayspossibleforanimplementationtoexpandsynonymsinthiswaybecauseHaskellpreventstheuseofasynonymwithoutitsfullcomplementofarguments.Moreover,theprocessisguaranteedtoterminatebecauserecursivesynonymde-nitionsareprohibited.Inpractice,however,implementationsarelikelytoexpandsynonymsmorelazily:insomecases,typeerrordiagnosticsmaybeeasiertoun-derstandiftheydisplaysynonymsratherthanexpansions.Weendthissectionwiththedenitionofafewhelperfunctions.Therstthreeprovidesimplewaystoconstructfunction,list,andpairtypes,respectively:inxr4`fn`fn::Type!Type!Typea`fn`b=TAp(TAptArrowa)blist::Type!Typelistt=TAptListt 8M.P.Jonescomponents|inanaturalway.Thissuggeststhatweoverloadtheoperationtoapplyasubstitutionsothatitcanworkondierenttypesofobject:classTypestwhereapply::Subst!t!ttv::t![Tyvar]Ineachcase,thepurposeofapplyingasubstitutionisthesame:Toreplaceeveryoccurrenceofatypevariableinthedomainofthesubstitutionwiththecorre-spondingtype.Wealsoincludeafunctiontvthatreturnsthesetoftypevariables(i.e.,Tyvars)appearinginitsargument,listedinorderofrstoccurrence(fromlefttoright),withnoduplicates.ThedenitionsoftheseoperationsforTypeareasfollows:instanceTypesTypewhereapplys(TVaru)=caselookupusofJustt!tNothing!TVaruapplys(TAplr)=TAp(applysl)(applysr)applyst=ttv(TVaru)=[u]tv(TAplr)=tvl`union`tvrtvt=[]Itisstraightforward(anduseful!)toextendtheseoperationstoworkonlists:instanceTypesa)Types[a]whereapplys=map(applys)tv=nub:concat:maptvTheapplyfunctioncanbeusedtobuildmorecomplexsubstitutions.Forexample,compositionofsubstitutions,satisfyingapply(s1@@s2)=applys1:applys2,canbedenedusing:inxr4@@(@@)::Subst!Subst!Substs1@@s2=[(u;applys1t)j(u;t) s2]++s1Wecanalsoforma`parallel'compositions1++s2oftwosubstitutionss1ands2,buttheresultisleft-biasedbecausebindingsins1takeprecedenceoveranybindingsforthesamevariablesins2.Foramoresymmetricversionofthisoperation,weuseamergefunction,whichchecksthatthetwosubstitutionsagreeateveryvariableinthedomainofbothandhenceguaranteesthatapply(s1++s2)=apply(s2++s1).Clearly,thisisapartialfunction,whichwere ectbyarrangingformergetoreturnitsresultinamonad,usingthestandardfailfunctiontoprovideastringdiagnostic 10M.P.JonesThevarBindfunctionisusedforthespecialcaseofunifyingavariableuwithatypet.Atrstglance,onemightthinkthatwecouldjustusethesubstitution(u7!t)forthis.Inpractice,however,testsarerequiredtoensurethatthisisvalid,includingan`occurscheck'(u`elem`tvt)andatesttoensurethatthesubstitutioniskind-preserving:varBindutjt==TVaru=returnnullSubstju`elem`tvt=fail\occurscheckfails"jkindu==kindt=fail\kindsdonotmatch"jotherwise=return(u7!t)Inthefollowingsections,wewillalsomakeuseofanoperationcalledmatchingthatiscloselyrelatedtounication.Giventwotypest1andt2,thegoalofmatchingistondasubstitutionssuchthatapplyst1=t2.Becausethesubstitutionisappliedonlytoonetype,thisoperationisoftendescribedasone-waymatching.Thecalculationofmatchingsubstitutionsisimplementedbyafunction:match::Monadm)Type!Type!mSubstMatchingfollowsthesamepatternasunication,exceptthatitusesmergeratherthan@@tocombinesubstitutions,anditdoesnotallowbindingofvariablesint2:match(TAplr)(TApl0r0)=dosl matchll0sr matchrr0mergeslsrmatch(TVaru)tjkindu==kindt=return(u7!t)match(TContc1)(TContc2)jtc1==tc2=returnnullSubstmatcht1t2=fail\typesdonotmatch"7TypeClasses,PredicatesandQualiedTypesOneofthemostunusualfeaturesoftheHaskelltypesystem,atleastincomparisontothoseofotherpolymorphicallytypedlanguageslikeML,isthesupportthatitprovidesfortypeclasses.DescribedbyWadlerandBlott(1989)asageneralmech-anismthatsubsumesseveralad-hocformsofoverloading,typeclasseshavefoundmanyuses(and,sometimes,abuses!)inthetenyearssincetheywereintroduced.Asignicantportionofthecodepresentedinthispaper,particularlyinthissection,isneededtodescribethehandlingoftypeclassesinHaskell.(Ofcourse,typeclassesarenottheonlysourceofcomplexity.Thetreatmentofmixedimplicitandexplicittyping,mutuallyrecursivebindings,andpatternmatching|whichareoftenelidedinmoretheoreticalpresentations|arealsosignicantcontributors,asistheextralevelofdetailandprecisionthatisneededinexecutablecode.)7.1BasicDenitionsAHaskelltypeclasscanbethoughtofasasetoftypes(ofsomeparticularkind),eachofwhichsupportsacertaincollectionofmemberfunctionsthatarespecied 12M.P.Jonessuperclass,andanothercontaininganentryforeachinstancedeclaration:typeClass=([Id];[Inst])typeInst=QualPredForexample,asimpliedversionofthestandardHaskellclassOrdmightbede-scribedbythefollowingvalueoftypeClass:([\Eq"];[[]:)IsIn\Ord"tUnit;[]:)IsIn\Ord"tChar;[]:)IsIn\Ord"tInt;[IsIn\Ord"(TVar(Tyvar\a"Star));IsIn\Ord"(TVar(Tyvar\b"Star))]:)IsIn\Ord"(pair(TVar(Tyvar\a"Star))(TVar(Tyvar\b"Star)))])ThisstructurecapturesthefactthatEqisasuperclassofOrd(theonlyoneinfact),andlistsfourinstancedeclarationsfortheunit,character,integer,andpairtypes(ifaandbareinOrd,then(a;b)isalsoinOrd).Ofcourse,thisisonlyafractionofthelistofOrdinstancesthataredenedinthefullHaskellprelude.Onlythedetailsthatareneededfortypeinferenceareincludedintheserepresentations.AfullHaskellimplementationwouldneedtostoreadditionalinformationforeachdeclaration,suchasthelistofmemberfunctionsforeachclassanddetailsoftheirimplementationsineachparticularinstance.7.2ClassEnvironmentsTheinformationprovidedbytheclassandinstancedeclarationsinagivenprogramcanbecapturedbyaclassenvironmentoftype:dataClassEnv=ClassEnvfclasses::Id!MaybeClass;defaults::[Type]gTheclassescomponentinaClassEnvvalueisapartialfunctionthatmapsidenti-erstoClassvalues(ortoNothingifthereisnoclasscorrespondingtothespeciedidentier).Wedenehelperfunctionssuperandinststoextractthelistofsuper-classidentiers,andthelistofinstances,respectively,foraclassnameiinaclassenvironmentce:super::ClassEnv!Id![Id]supercei=caseclassesceiofJust(is;its)!isinsts::ClassEnv!Id![Inst]instscei=caseclassesceiofJust(is;its)!itsThesefunctionsareintendedtobeusedonlyincaseswhereitisknownthattheclassiisdenedintheenvironmentce.Insomecases,thisconditionmightbeguaranteedbystaticanalysispriortotypechecking.Alternatively,wecanresorttoadynamiccheckbytestingdened(classescei)beforeapplyingeitherfunction. 14M.P.JonesSomereaderswillrecognizethisasaspecialcaseofthemoregeneralKleislicompo-sitionoperator;withoutthetypedeclaration,thedenitiongivenherewouldworkforanymonadandforanyelementtypes,notjustforMaybeandClassEnv.Toaddanewclasstoanenvironment,wemustcheckthatthereisnotalreadyaclasswiththesamename,andthatallofthenamedsuperclassesarealreadydened.ThisisasimplewayofenforcingHaskell'srestrictionthatthesuperclasshierarchybeacyclic.Ofcourse,inpractice,itwillbenecessarytotopologicallysortthesetofclassdeclarationsinaprogramtodetermineasuitableordering;anycyclesinthehierarchywilltypicallybedetectedatthisstage.addClass::Id![Id]!EnvTransformeraddClassiiscejdened(classescei)=fail\classalreadydefined"jany(not:dened:classesce)is=fail\superclassnotdefined"jotherwise=return(modifycei(is;[]))Forexample,wecandescribetheeectoftheclassdeclarationsintheHaskellpreludeusingthefollowingtransformer:addPreludeClasses::EnvTransformeraddPreludeClasses=addCoreClasses:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addNumClassesThisdenitionbreaksdownthesetofstandardHaskellclassesintotwoseparatepieces.Thecoreclassesaredescribedasfollows:addCoreClasses::EnvTransformeraddCoreClasses=addClass\Eq"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Ord"[\Eq"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Show"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Read"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Bounded"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Enum"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Functor"[]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Monad"[]Thehierarchyofnumericclassesiscapturedseparatelyinthefollowingdenition:addNumClasses::EnvTransformeraddNumClasses=addClass\Num"[\Eq";\Show"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Real"[\Num";\Ord"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Fractional"[\Num"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Integral"[\Real";\Enum"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\RealFrac"[\Real";\Fractional"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\Floating"[\Fractional"]:]TJ/;ø 9;.963; Tf ;.74; 0 ;Td[0;addClass\RealFloat"[\RealFrac";\Floating"]Toaddanewinstancetoaclass,wemustcheckthattheclasstowhichtheinstanceappliesisdened,andthatthenewinstancedoesnotoverlapwithanypreviously 16M.P.Jonestheheadofaninstanceshouldconsistofatypeconstructorappliedtoasequenceofdistincttypevariablearguments.Becausetheseconditionshavenodirectimpactontypechecking,andbecausetheyarestraightforwardbuttedioustoverify,wehavechosennottoincludetestsforthemhere,andinsteadassumethattheyhavebeencheckedduringstaticanalysispriortotypechecking.7.3EntailmentInthissection,wedescribehowclassenvironmentscanbeusedtoanswerquestionsaboutwhichtypesareinstancesofparticularclasses.Moregenerally,weconsiderthetreatmentofentailment:givenapredicatepandalistofpredicatesps,ourgoalistodeterminewhetherpwillholdwheneverallofthepredicatesinpsaresatised.Inthespecialcasewherep=IsInitandps=[],thisamountstodeterminingwhethertisaninstanceoftheclassi.Inthetheoryofqualiedtypes(Jones,1992),assertionslikethisarecapturedusingjudgementsoftheformps``p;weuseadierentnotationhere|theentailfunctionthatisdenedattheendofthissection|tomakethedependenceonaclassenvironmentexplicit.Asarststep,wecanaskhowinformationaboutsuperclassesandinstancescanbeusedindependentlytohelpreasonaboutentailments.Forexample,ifatypeisaninstanceofaclassi,thenitmustalsobeaninstanceofanysuperclassesofi.Hence,usingonlysuperclassinformation,wecanbesurethat,ifagivenpredicatepholds,thensotoomustallofthepredicatesinthelistbySuperp:bySuper::ClassEnv!Pred![Pred]bySupercep@(IsInit)=p:concat[bySuperce(IsIni0t)ji0 supercei]ThelistbySupercepmaycontainduplicates,butitwillalwaysbenitebecauseoftherestrictionthatthesuperclasshierarchyisacyclic.Nextweconsiderhowinformationaboutinstancescanbeused.Ofcourse,foragivenpredicatep=IsInit,wecanndallthedirectlyrelevantinstancesinaclassenvironmentcebylookingininstscei.Aswehaveseen,individualinstancedeclarationsaremappedintoclausesoftheformps:)h.Theheadpredicatehdescribesthegeneralformofinstancesthatcanbeconstructedfromthisdeclara-tion,andwecanusematchPredtodeterminewhetherthisinstanceisapplicabletothegivenpredicatep.Ifitisapplicable,thenmatchingwillreturnasubstitutionu,andtheremainingsubgoalsaretheelementsofmap(applyu)ps.Thefollowingfunctionusestheseideastodeterminethelistofsubgoalsforagivenpredicate:byInst::ClassEnv!Pred!Maybe[Pred]byInstcep@(IsInit)=msum[tryInstitjit instscei]wheretryInst(ps:)h)=dou matchPredhpJust(map(applyu)ps)ThemsumfunctionusedherecomesfromthestandardMonadlibrary,andreturnstherstdenedelementinalistofMaybevalues;iftherearenodenedelementsinthelist,thenitreturnsNothing.BecauseHaskellpreventsoverlappinginstances, 18M.P.Jonesofa,eachoneofthesepredicatesholdsif,andonlyif,Eqaholds.Noticethat,insomecases,anattempttosimplifytypecomponents|forexample,byreplacingEq(a,b)with(Eqa,Eqb)|mayincreasethenumberofpredicatesinthelist.Theextenttowhichsimplicationslikethisareusedinasystemofqualiedtypeshasanimpactontheimplementationandperformanceofoverloadinginpracticalsystems(Jones,1992;Chapter7).InHaskell,however,thedecisionsaremadeforusbyasyntacticrestrictionthatforcesustosimplifypredicatesuntilweobtaintypesinakindof`head-normalform'.Thisterminologyismotivatedbysimilaritieswiththeconceptofhead-normalformsin-calculus.Moreprecisely,thesyntaxofHaskellrequiresclassargumentstobeoftheformvt1:::tn,wherevisatypevariable,andt1,...,tnaretypes(andn0).Thefollowingfunctionallowsustodeterminewhetheragivenpredicatemeetstheserestrictions:inHnf::Pred!BoolinHnf(IsInct)=hnftwherehnf(TVarv)=Truehnf(TContc)=Falsehnf(TApt )=hnftPredicatesthatdonottthispatternmustbebrokendownusingbyInst.Insomecases,thiswillresultinpredicatesbeingeliminatedaltogether.Inothers,wherebyInstfails,itwillindicatethatapredicateisunsatisable,andwilltriggeranerrordiagnostic.Thisprocessiscapturedinthefollowingdenition:toHnfs::Monadm)ClassEnv![Pred]!m[Pred]toHnfsceps=dopss mapM(toHnfce)psreturn(concatpss)toHnf::Monadm)ClassEnv!Pred!m[Pred]toHnfcepjinHnfp=return[p]jotherwise=casebyInstcepofNothing!fail\contextreduction"Justps!toHnfscepsAnotherwaytosimplifyalistofpredicatesistoreducethenumberofelementsthatitcontains.Thereareseveralwaysthatthismightbeachieved:byremovingduplicates(e.g.,reducing(Eqa,Eqa)toEqa);byeliminatingpredicatesthatarealreadyknowntohold(e.g.,removinganyoccurrencesofNumInt);orbyusingsuperclassinformation(e.g.,reducing(Eqa,Orda)toOrda).Ineachcase,thereducedlistofpredicates,isequivalenttotheinitiallist,meaningthatallthepredicatesintherstwillbesatisedif,andonlyif,allofthepredicatesinthesecondaresatised.Thesimplicationalgorithmthatwewillusehereisbasedontheobservationthatapredicatepinalistofpredicates(p:ps)canbeeliminatedifpisentailedbyps.Asaspecialcase,thiswilleliminateduplicatedpredicates:ifpisrepeatedinps,thenitwillalsobeentailedbyps.Theseideasareusedinthefollowingdenitionofthesimplifyfunction,whichloopsthrougheachpredicateinthelistandusesanaccumulatingparametertobuildupthenalresult.Eachtime 20M.P.Jonesbesurethattherewillbenovariablecaptureproblemsinthefollowingdenition:instanceTypesSchemewhereapplys(Forallksqt)=Forallks(applysqt)tv(Forallksqt)=tvqtTypeschemesareconstructedbyquantifyingaqualiedtypeqtwithrespecttoalistoftypevariablesvs:quantify::[Tyvar]!QualType!Schemequantifyvsqt=Forallks(applysqt)wherevs0=[vjv tvqt;v`elem`vs]ks=mapkindvs0s=zipvs0(mapTGen[0::])Notethattheorderofthekindsinksisdeterminedbytheorderinwhichthevariablesvappearintvqt,andnotbytheorderinwhichtheyappearinvs.So,forexample,theleftmostquantiedvariableinatypeschemewillalwaysberepresentedbyTGen0.Byinsistingthattypeschemesareconstructedinthisway,weobtainauniquecanonicalformforSchemevalues.Thisisimportantbecauseitmeansthatwecantestwhethertwotypeschemesarethesame|forexample,todeter-minewhetheraninferredtypeagreeswithadeclaredtype|usingHaskell'sderivedequality,andwithouthavingtoimplementmorecomplextestsfor-equivalence.Inpractice,wesometimesneedtoconvertaTypeintoaSchemewithoutaddinganyqualifyingpredicatesorquantiedvariables.Forthisspecialcase,wecanusethefollowingfunctioninsteadofquantify:toScheme::Type!SchemetoSchemet=Forall[]([]:)t)Tocompleteourdescriptionoftypeschemes,weneedtobeabletoinstantiatethequantiedvariablesinSchemevalues.Infact,forthepurposesoftypeinference,weonlyneedthespecialcasethatinstantiatesatypeschemewithfreshtypevariables.WethereforedeferfurtherdescriptionofinstantiationtoSection10wherethemechanismsforgeneratingfreshtypevariablesareintroduced.9AssumptionsAssumptionsaboutthetypeofavariablearerepresentedbyvaluesoftheAssumpdatatype,eachofwhichpairsavariablenamewithatypescheme:dataAssump=Id::SchemeOnceagain,wecanextendtheTypesclasstoallowtheapplicationofasubsti-tutiontoanassumption:instanceTypesAssumpwhereapplys(i::sc)=i::(applyssc)tv(i::sc)=tvsc 22M.P.JonesForclarity,wedenetheoperationthatextendsthesubstitutionasaseparatefunction,eventhoughitisusedonlyhereinthedenitionofunify:extSubst::Subst!TI()extSubsts0=TI(nsn!(s0@@s;n;()))Overall,thedecisiontohidethecurrentsubstitutionintheTImonadmakesthepresentationoftypeinferencemuchclearer.Inparticular,itavoidsheavyuseofapplyeverytimeanextensionis(ormighthavebeen)computed.Thereisonlyoneprimitivethatdealswiththeintegerportionofthestate,usingitincombinationwithenumIdtogenerateanewtypevariableofaspeciedkind:newTVar::Kind!TITypenewTVark=TI(nsn!letv=Tyvar(enumIdn)kin(s;n+1;TVarv))OneplacewherenewTVarisusefulisininstantiatingatypeschemewithnewtypevariablesofappropriatekinds:freshInst::Scheme!TI(QualType)freshInst(Forallksqt)=dots mapMnewTVarksreturn(insttsqt)Thestructureofthisdenitionguaranteesthattshasexactlytherightnumberoftypevariables,andeachwiththerightkind,tomatchks.Hence,ifthetypeschemeiswell-formed,thenthequaliedtypereturnedbyfreshInstwillnotcontainanyunboundgenericsoftheformTGenn.Thedenitionreliesonanauxiliaryfunctioninst,whichisavariationofapplythatworksongenericvariables.Inotherwords,insttstreplaceseachoccurrenceofagenericvariableTGennintwithts!!n.Itisconvenienttobuildupthedenitionofinstusingoverloading:classInstantiatetwhereinst::[Type]!t!tinstanceInstantiateTypewhereinstts(TAplr)=TAp(insttsl)(insttsr)instts(TGenn)=ts!!ninsttst=tinstanceInstantiatea)Instantiate[a]whereinstts=map(instts)instanceInstantiatet)Instantiate(Qualt)whereinstts(ps:)t)=insttsps:)insttstinstanceInstantiatePredwhereinstts(IsInct)=IsInc(insttst)11TypeInferenceWiththissectionwehavereachedtheheartofthepaper,detailingouralgorithmfortypeinference.Itisherethatwenallyseehowthemachinerythathasbeenbuiltupinearliersectionsisactuallyputtouse.Wedevelopthecompletealgorithmin 24M.P.Jonessions.WewillrepresentpatternsusingvaluesofthePatdatatype:dataPat=PVarIdjPWildcardjPAsIdPatjPLitLiteraljPNpkIdIntegerjPConAssump[Pat]APVaripatternmatchesanyvalueandbindstheresulttothevariablei.APWildcardpattern,correspondingtoanunderscore inHaskellsyntax,matchesanyvalue,butdoesnotbindanyvariables.Apatternoftheform(PAsipat),knownasan\as-pattern"andwrittenusingthesyntaxi@patinHaskell,bindsthevariableitoanyvaluethatmatchesthepatternpat,whilealsobindinganyvariablesthatappearinpat.APLitlpatternmatchesonlytheparticularvaluedenotedbytheliterall.Apattern(PNpkik)isan(n+k)pattern,whichmatchesanypositiveintegralvaluemthatisgreaterthanorequaltok,andbindsthevariableitothedierence(mk).Finally,apatternoftheformPConapatsmatchesonlyvaluesthatwerebuiltusingtheconstructorfunctionawithasequenceofargumentsthatmatchespats.WeusevaluesaoftypeAssumptorepresentconstructorfunctions;allthatwereallyneedfortypecheckingisthetype,althoughthenameisusefulfordebugging.Afullimplementationwouldstoreadditionaldetails,suchasarity,andusethistocheckthatconstructorfunctionsinpatternsarealwaysfullyapplied.MostHaskellpatternshaveadirectrepresentationinPat,butextensionswouldbeneededtoaccountforpatternsusinglabeledelds.Thisisnotdicult,butaddssomecomplexity,whichweprefertoavoidinthispresentation.Typeinferenceforpatternshastwogoals:Tocalculateatypeforeachboundvariable,andtodeterminewhattypeofvaluesthewholepatternmightmatch.Thisleadsustolookforafunction:tiPat::Pat!TI([Pred];[Assump];Type)Notethatwedonotneedtopassinalistofassumptionshere;bydenition,anyoccurrenceofavariableinapatternwouldhideratherthanrefertoavariableofthesamenameinanenclosingscope.Foravariablepattern,PVari,wejustreturnanewassumption,bindingitoafreshtypevariable.tiPat(PVari)=dov newTVarStarreturn([];[i::toSchemev];v)Haskelldoesnotallowmultipleuseofanyvariableinapattern,sowecanbesurethatthisistherstandonlyoccurrenceofithatwewillencounterinthepattern.Wildcardsaretypedinthesamewayexceptthatwedonotneedtocreateanewassumption:tiPatPWildcard=dov newTVarStarreturn([];[];v)Totypeanas-patternPAsipat,wecalculateasetofassumptionsandatypefor 26M.P.Jones11.3ExpressionsNextwedescribetypeinferenceforexpressions,representedbytheExprdatatype:dataExpr=VarIdjLitLiteraljConstAssumpjApExprExprjLetBindGroupExprTheVarandLitconstructorsareusedtorepresentvariablesandliterals,respec-tively.TheConstconstructorisusedtodealwithnamedconstants,suchastheconstructororselectorfunctionsassociatedwithaparticulardatatypeorthemem-berfunctionsthatareassociatedwithaparticularclass.WeusevaluesoftypeAssumptosupplyanameandtypescheme,whichisalltheinformationthatweneedforthepurposesoftypeinference.FunctionapplicationisrepresentedusingtheApconstructor,whileLetisusedtorepresentletexpressions.(NotethatthedenitionoftheBindGrouptype,usedheretorepresentbindinggroups,willbedelayedtoSection11.6.3.)Ofcourse,Haskellhasamuchrichersyntaxofexpressions|whichincludes-abstractions,caseexpressions,conditionals,listcomprehensions,anddo-notation|buttheyallhavesimpletranslationsintoExprvalues.Forexample,a-expressionlike\x-ecanberewrittenusingalocalde-nitionasletfx=einf,wherefisanewvariable.Typeinferenceforexpressionsisquitestraightforward:tiExpr::InferExprTypetiExprceas(Vari)=dosc ndias(ps:)t) freshInstscreturn(ps;t)tiExprceas(Const(i::sc))=do(ps:)t) freshInstscreturn(ps;t)tiExprceas(Litl)=do(ps;t) tiLitlreturn(ps;t)tiExprceas(Apef)=do(ps;te) tiExprcease(qs;tf) tiExprceasft newTVarStarunify(tf`fn`t)tereturn(ps++qs;t)tiExprceas(Letbge)=do(ps;as0) tiBindGroupceasbg(qs;t) tiExprce(as0++as)ereturn(ps++qs;t)Thenalcasehere,forLetexpressions,usesthefunctiontiBindGrouppresentedinSection11.6.3,togeneratealistofassumptionsas0forthevariablesdenedinbg.Allofthesevariablesareinscopewhenwecalculateatypetforthebodye,whichalsoservesasthetypeofthewholeexpression. 28M.P.JonesTounderstandthebasicproblem,supposethatwehaverunthetypecheckeroverthebodyofafunctionhtoobtainalistofpredicatespsandatypet.Atthispoint,toobtainthemostgeneralresult,wecouldinferatypeforhbyformingthequaliedtypeqt=(ps:)t)andthenquantifyingoveranyvariablesinqtthatdonotappearintheassumptions.Whilethisispermittedbythetheoryofqualiedtypes,itisoftennotthebestthingtodoinpractice.Forexample:Thelistpscanoftenbesimpliedusingthecontextreductionprocessde-scribedinSection7.4.ThiswillalsoensurethatthesyntacticrestrictionsofHaskellaremet,requiringallpredicatestobeinhead-normalform.Someofthepredicatesinpsmaycontainonly`xed'variables(i.e.,variablesappearingintheassumptions),soincludingthoseconstraintsintheinferredtypewillnotbeofanyuse(Jones,1992;Section6.1.4).Thesepredicatesshouldbe`deferred'totheenclosingbindings.Someofthepredicatesinpscouldresultinambiguity,andrequiredefaultingtoavoidatypeerror.ThisaspectofHaskell'stypesystemwillbedescribedshortlyinSection11.5.1.Inthispaperweuseafunctioncalledsplittoaddresstheseissues.Forthesituationdescribedpreviouslywherewehaveinferredatypetandalistofpredicatespsforafunctionh,wecanusesplittorewriteandbreakpsintoapair(ds;rs)ofdeferredpredicatesdsand`retained'predicatesrs.Thepredicatesinrswillbeusedtoformaninferredtype(rs:)t)forh,whilethepredicatesindswillbepassedoutasconstraintstotheenclosingscope.Weusethefollowingdenitionforsplit:split::Monadm)ClassEnv![Tyvar]![Tyvar]![Pred]!m([Pred];[Pred])splitcefsgsps=dops0 reducecepslet(ds;rs)=partition(all(`elem`fs):tv)ps0rs0 defaultedPredsce(fs++gs)rsreturn(ds;rsnnrs0)Inadditiontoalistofpredicatesps,thesplitfunctionisparameterizedbytwolistsoftypevariables.Therst,fs,speciesthesetof`xed'variables,whicharejustthevariablesappearingfreeintheassumptions.Thesecond,gs,speciesthesetofvariablesoverwhichwewouldliketoquantify;fortheexampleabove,itwouldjustbethevariablesin(tvtnnfs).Itispossibleforpstocontainvariablesthatarenotineitherfsorgs(andhencenotintheparameter(fs++gs)thatispassedtodefaultedPreds).InSection11.5.1wewillseethatthisisanindicationofambiguity.Therearethreestagesinthesplitfunction,correspondingdirectlytothethreepointslistedpreviously.Therststageusesreducetoperformcontextreduction.Thesecondstageusesthestandardpreludefunctionpartitiontoidentifythede-ferredpredicates,ds;thesearejustthepredicatesinps0thatcontainonlyxedtypevariables.ThethirdstagedetermineswhetheranyofthepredicatesinrsshouldbeeliminatedusingHaskell'sdefaultingmechanism,andproducesalistofallsuchpredicatesinrs0.Hencethenalsetofretainedpredicatesisproducedbytheexpressionrsnnrs0inthelastlineofthedenition. 30M.P.Jonesdefaultingistobindeachambiguoustypevariablevtoamonotypet.Thetypetmustbechosensothatallofthepredicatesinpsthatinvolvevwillbesatisedoncethasbeensubstitutedforv.Thefollowingfunctioncalculatesthelistofambiguousvariablesandpairseachonewiththelistofpredicatesthatmustbesatisedbyanychoiceofadefault:typeAmbiguity=(Tyvar;[Pred])ambiguities::ClassEnv![Tyvar]![Pred]![Ambiguity]ambiguitiescevsps=[(v;lter(elemv:tv)ps)jv tvpsnnvs]Givenoneofthesepairs(v;qs),andasspeciedbytheHaskellreport(PeytonJones&Hughes,1999;Section4.3.4),defaultingispermittedif,andonlyif,allofthefollowingconditionsaresatised:AllofthepredicatesinqsareoftheformIsInc(TVarv)forsomeclassc.Atleastoneoftheclassesinvolvedinqsisastandardnumericclass.Thelistoftheseclassnamesisprovidedbyaconstant:numClasses::[Id]numClasses=[\Num";\Integral";\Floating";\Fractional";\Real";\RealFloat";\RealFrac"]Alloftheclassesinvolvedinqsarestandardclasses,denedeitherinthestandardpreludeorstandardlibraries.Again,thelistoftheseclassnamesisprovidedbyaconstant:stdClasses::[Id]stdClasses=[\Eq";\Ord";\Show";\Read";\Bounded";\Enum";\Ix";\Functor";\Monad";\MonadPlus"]++numClassesThatthereisatleastonetypeinthelistofdefaulttypesfortheenclosingmodulethatisaninstanceofalloftheclassesmentionedinqs.Therstsuchtypewillbeselectedasthedefault.ThelistofdefaulttypescanbeobtainedfromaclassenvironmentbyusingthedefaultsfunctionthatwasdescribedinSection7.2.Theseconditionsarecapturedrathermoresuccinctlyinthefollowingdenition,whichweusetocalculatethecandidatesforresolvingaparticularambiguity:candidates::ClassEnv!Ambiguity![Type]candidatesce(v;qs)=[t0jletis=[ijIsInit qs]ts=[tjIsInit qs];all((TVarv)==)ts;any(`elem`numClasses)is;all(`elem`stdClasses)is;t0 defaultsce;all(entailce[])[IsInit0ji is]]Ifcandidatesreturnsanemptylistforagivenambiguity,thendefaultingcannotbeappliedtothecorrespondingvariable,andtheambiguitycannotbeavoided.Onthe 32M.P.Jones11.6.1ExplicitlyTypedBindingsThesimplestcaseisforexplicitlytypedbindings,eachofwhichisdescribedbythenameofthefunctionthatisbeingdened,thedeclaredtypescheme,andthelistofalternativesinitsdenition:typeExpl=(Id;Scheme;[Alt])HaskellrequiresthateachAltinthedenitionofagivenidentierhasthesamenumberofleft-handsidearguments,butwedonotneedtoenforcethathere.Typeinferenceforanexplicitlytypedbindingisfairlyeasy;weneedonlycheckthatthedeclaredtypeisvalid,anddonotneedtoinferatypefromrstprinciples.Tosupporttheuseofpolymorphicrecursion(Henglein,1993;Kfouryetal.,1993),wewillassumethatthedeclaredtypingforiisalreadyincludedintheassumptionswhenwecallthefollowingfunction:tiExpl::ClassEnv![Assump]!Expl!TI[Pred]tiExplceas(i;sc;alts)=do(qs:)t) freshInstscps tiAltsceasaltsts getSubstletqs0=applysqst0=applystfs=tv(applysas)gs=tvt0nnfssc0=quantifygs(qs0:)t0)ps0=lter(not:entailceqs0)(applysps)(ds;rs) splitcefsgsps0ifsc==sc0thenfail\signaturetoogeneral"elseifnot(nullrs)thenfail\contexttooweak"elsereturndsThiscodebeginsbyinstantiatingthedeclaredtypeschemescandcheckingeachalternativeagainsttheresultingtypet.Whenallofthealternativeshavebeenprocessed,theinferredtypeforiisqs0:)t0.Ifthetypedeclarationisaccurate,thenthisshouldbethesame,uptorenamingofgenericvariables,astheoriginaltypeqs:)t.Ifthetypesignatureistoogeneral,thenthecalculationofsc0willresultinatypeschemethatismorespecicthanscandanerrorwillbereported.Inthemeantime,wemustdischargeanypredicatesthatweregeneratedwhilecheckingthelistofalternatives.Predicatesthatareentailedbythecontextqs0canbeeliminatedwithoutfurtherado.Anyremainingpredicatesarecollectedinps0andpassedasargumentstosplitalongwiththeappropriatesetsofxedandgenericvariables.Ifthereareanyretainedpredicatesaftercontextreduction,thenanerrorisreported,indicatingthatthedeclaredcontextistooweak. 34M.P.Jonesusesplittobreaktheinferredpredicatesinps0intoalistofdeferredpredicatesdsandretainedpredicatesrs.Thelistgscollectsallthegenericvariablesthatappearinoneormoreoftheinferredtypests0,butnotinthelistfsofxedvariables.Notethatadierentlistispassedtosplit,includingonlyvariablesthatappearinalloftheinferredtypes.Thisisimportantbecauseallofthosetypeswilleventuallybequaliedbythesamesetofpredicates,andwedonotwantanyoftheresultingtypeschemestobeambiguous.Thenalstepbeginswithatesttoseeifthemonomor-phismrestrictionshouldbeapplied,andthencontinuestocalculateanassumptioncontainingtheprincipaltypesforeachofthedenedvalues.Foranunrestrictedbinding,thisissimplyamatterofqualifyingovertheretainedpredicatesinrsandquantifyingoverthegenericvariablesings.Ifthebindinggroupisrestricted,thenwemustdeferthepredicatesinrsaswellasthoseinds,andhencewecanonlyquantifyovervariablesingsthatdonotappearinrs.11.6.3CombinedBindingGroupsHaskellrequiresaprocessofdependencyanalysistobreakdowncompletesetsofbindings|eitheratthetop-levelofaprogram,orwithinalocaldenition|intothesmallestpossiblegroupsofmutuallyrecursivedenitions,andorderedsothatnogroupdependsonthevaluesdenedinlatergroups.Thisisnecessarytoobtainthemostgeneraltypespossible.Forexample,considerthefollowingfragmentfromastandardpreludeforHaskell:foldrfa(x:xs)=fx(foldrfaxs)foldrfa[]=aandxs=foldr(&&)TruexsIfthesedenitionswereplacedinthesamebindinggroup,thenwewouldnotobtainthemostgeneralpossibletypeforfoldr;alloccurrencesofavariablearerequiredtohavethesametypeateachpointwithinthedeningbindinggroup,whichwouldleadtothefollowingtypeforfoldr:(Bool-Bool-Bool)-Bool-[Bool]-BoolToavoidthisproblem,weneedonlynoticethatthedenitionoffoldrdoesnotdependinanywayon&&,andhencewecanplacethetwofunctionsinseparatebindinggroups,inferringrstthemostgeneraltypeforfoldr,andthenthecorrecttypeforand.Inthepresenceofexplicitlytypedbindings,wecanrenethedependencyanalysisprocessalittlefurther.Forexample,considerthefollowingpairofbindings:f::Eqa=a-Boolfx=(x==x)||gTruegy=(y)||fTrueAlthoughthesebindingsaremutuallyrecursive,wedonotneedtoinfertypesforfandgatthesametime.Instead,wecanusethedeclaredtypeofftoinferatype:g::Orda=y-5;─=a=y-5;─-Boolandthenusethistocheckthebodyoff,ensuringthatitsdeclaredtypeiscorrect. 36M.P.Jonesthatincludesoneasrestricted.Soitmayseemthatthedenitionofrestrictedbindinggroupsinthispaperisnotquiteaccurate.However,ifweusetranslationsassuggestedhere,thenitturnsouttobeequivalent:eveniftheprogrammersuppliesexplicittypesignaturesforxandyintheoriginalprogram,thetranslationwillstillcontainanimplicitlytypedbindingforthenewvariablenv.Now,atlast,wearereadytopresentthealgorithmfortypeinferenceofacom-pletebindinggroup,asimplementedbythefollowingfunction:tiBindGroup::InferBindGroup[Assump]tiBindGroupceas(es;iss)=doletas0=[v::scj(v;sc;alts) es](ps;as00) tiSeqtiImplsce(as0++as)issqss mapM(tiExplce(as00++as0++as))esreturn(ps++concatqss;as00++as0)Thestructureofthisdenitionisquitestraightforward.Firstweformalistofassumptionsas0foreachoftheexplicitlytypedbindingsinthegroup.Next,weusethistocheckeachgroupofimplicitlytypedbindings,extendingtheassumptionsetfurtherateachstage.Finally,wereturntotheexplicitlytypedbindingstoverifythateachofthedeclaredtypesisacceptable.Indealingwiththelistofimplicitlytypedbindinggroups,weusethefollowingutilityfunction,whichtypechecksalistofbindinggroupsandaccumulatesassumptionsasitrunsthroughthelist:tiSeq::Inferbg[Assump]!Infer[bg][Assump]tiSeqticeas[]=return([];[])tiSeqticeas(bs:bss)=do(ps;as0) ticeasbs(qs;as00) tiSeqtice(as0++as)bssreturn(ps++qs;as00++as0)11.6.4Top-levelBindingGroupsAtthetop-level,aHaskellprogramcanbethoughtofasalistofbindinggroups:typeProgram=[BindGroup]Eventhedenitionsofmemberfunctionsinclassandinstancedeclarationscanbeincludedinthisrepresentation;theycanbetranslatedintotop-level,explicitlytypedbindings.Thetypeinferenceprocessforaprogramtakesalistofassumptionsgivingthetypesofanyprimitives,andreturnsasetofassumptionsforanyvariables.tiProgram::ClassEnv![Assump]!Program![Assump]tiProgramceasbgs=runTI$do(ps;as0) tiSeqtiBindGroupceasbgss getSubstrs reducece(applysps)s0 defaultSubstce[]rsreturn(apply(s0@@s)as0)ThiscompletesourpresentationoftheHaskelltypesystem. 38M.P.JonesMilner,R.(1978).Atheoryoftypepolymorphisminprogramming.JournalofComputerandSystemSciences,17(3).PeytonJones,Simon,&Hughes,John(eds).(1999).ReportontheProgrammingLanguageHaskell98,ANon-strictPurelyFunctionalLanguage.Availablefromhttp://www.haskell.org/definition/.PeytonJones,Simon,Jones,Mark,&Meijer,Erik.(1997).Typeclasses:Exploringthedesignspace.Proceedingsofthesecondhaskellworkshop.Robinson,J.A.(1965).Amachine-orientedlogicbasedontheresolutionprinciple.JournaloftheAssociationforComputingMachinery,12.Wadler,P.(1992).Theessenceoffunctionalprogramming(invitedtalk).Pages1{14of:ConferencerecordoftheNineteenthannualACMSIGPLAN-SIGACTsymposiumonPrinciplesofProgrammingLanguages.Wadler,P.,&Blott,S.(1989).Howtomakeadhocpolymorphismlessadhoc.Pages60{76of:Proceedingsof16thACMSymposiumonPrinciplesofProgrammingLanguages.