nottacuk Ambrus Kaposi Functional Programming Laboratory University of Nottingham aukcsnottacuk Abstract Applicative functors 9 are a generalisation of monads Both allow expressing effectful computations into an otherwise pure language like Haskell 8 ID: 57153
Download Pdf The PPT/PDF document "Free Applicative Functors Paolo Capriott..." 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.
ThemeaningofFreeAfwillbeclariedinsection7,butforthesakeofthefollowingexamples,FreeAfcanbethoughtofasthesimplestapplicativefunctorwhichcanbebuiltusingf.1.2Example:optionparsersToillustratehowthefreeapplicativeconstructioncanbeusedinpractice,wetakeasarunningexampleaparserforoptionsofacommand-linetool.Forsimplicity,wewilllimitourselvestoaninterfacewhichcanonlyacceptoptionsthattakeasingleargument.Wewilluseadoubledashasaprexfortheoptionname.Forexample,atooltocreateanewuserinaUnixsystemcouldbeusedasfollows:create_user--usernamejohn\--fullname"JohnDoe"\--id1002Ourparsercouldberunovertheargumentlistanditwouldreturnarecordofthefollowingtype:dataUser=Userfusername::String,fullname::String,id::IntgderivingShowFurthermore,givenaparser,itshouldbepossibletoautomaticallyproduceasummaryofalltheoptionsthatitsupports,tobepre-sentedtotheuserofthetoolasdocumentation.Wecandeneadatastructurerepresentingaparserforanindivid-ualoption,withaspeciedtype,asafunctor:dataOptiona=OptionfoptName::String,optDefault::Maybea,optReader::String!MaybeagderivingFunctorWenowwanttocreateaDSLbasedontheOptionfunctor,whichwouldallowustocombineoptionsfordifferenttypesintoasinglevaluerepresentingthefullparser.Asstatedintheintroduction,acommonwaytocreateaDSLfromafunctoristousefreemonads.However,takingthefreemonadovertheOptionfunctorwouldnotbeveryusefulhere.Firstofall,sequencingofoptionsshouldbeindependent:lateroptionsshouldnotdependonthevalueparsedbypreviousones.Secondly,monadscannotbeinspectedwithoutrunningthem,sothereisnowaytoobtainasummaryofalloptionsofaparserautomatically.WhatwereallyneedisawaytoconstructaparserDSLinsuchawaythatthevaluesreturnedbytheindividualoptionscanbecombinedusinganApplicativeinterface.Andthat'sexactlywhatFreeAwillprovide.Thus,ifweuseFreeAOptionaasourembeddedDSL,wecaninterpretitasthetypeofaparserwithanunspeciednumberofoptions,ofpossiblydifferenttypes.Whenrun,thoseoptionswouldbematchedagainsttheinputcommandline,inanarbitraryorder,andtheresultingvalueswillbeeventuallycombinedtoobtainanalresultoftypea.Inourspecicexample,anexpressiontospecifythecommandlineoptionparserforcreate_userwouldlooklikethis:userP::FreeAOptionUseruserP=User$000;one(Option"username"NothingJust)*000;one(Option"fullname"(Just"")Just)*000;one(Option"id"NothingreadInt)readInt::String!MaybeIntwhereweneedagenericsmartconstructor:one::Optiona!FreeAOptionawhichliftsanoptiontoaparser.1.3Example:limitedIOOneoftheapplicationsoffreemonads,exempliedin[13],isthedenitionofspecial-purposemonads,allowingtoexpresscompu-tationswhichmakeuseofalimitedandwell-denedsubsetofIOoperations.Giventhefollowingfunctor:dataFileSystema=ReadFilePath(String!a)jWriteFilePathStringaderivingFunctorthefreemonadonFileSystem,oncesmartconstructorsaredenedforthetwobasicoperationsofreadingandwriting,allowstoexpressanyoperationonleswiththesameconvenienceastheIOmonad.Forexample,onecanimplementacopyoperationasfollows:copy::FilePath!FilePath!FreeFileSystem()copysrcdst=readsrc*000;*000;=writedstForsomeapplications,wemightneedtohavemorecontrolovertheoperationsthataregoingtobeexecutedwhenweeventu-allyruntheembeddedprogramcontainedinavalueoftypeFreeFileSystema.Forexample,itcouldbeusefultoprintasummaryofthelesthataregoingtobeoverwritten,andhowmuchdataintotalisgoingtobewrittentodisk.However,thereisnowaytodothatusingthefreemonadapproach.Forexample,thereisnofunction:count::FreeFileSystema!Intwhichreturnsthenumberofread/writeoperationsperformedbyamonadicvalue.Toseewhy,considerthefollowingexample:ex::FreeFileSystem()ex=dos read"/etc/motd"when(nulls)$write"/tmp/out"""Now,experforms1operationifandonlyif/etc/motdisempty,which,ofcourse,cannotbedeterminedbyapurefunctionlikecount.TheFreeAconstruction,presentedinthispaper,representsagen-eralsolutionfortheproblemofconstructingembeddedlanguagesthatallowthedenitionoffunctionsperformingstaticanalysisonembeddedprograms,ofwhichcount::FreeAFileSystema!Intisaverysimpleexample.1.4Example:applicativeparsersTheideathatmonadsaretooexiblehasalsobeenexplored,againinthecontextofparsing,bySwierstraandDuponcheel([12]),whoshowedhowtoimprovebothperformanceanderror-reportingcapabilitiesofanembeddedlanguageforgrammarsbygivingupsomeoftheexpressivityofmonads.Thebasicprincipleisthat,byweakeningthemonadicinterfacetothatofanapplicativefunctor(or,moreprecisely,analternativefunctor),itbecomespossibletoperformenoughstaticanalysistocomputerstsetsforproductions.Theapproachfollowedin[12]isad-hoc:anapplicativefunctorisdened,whichkeepstrackofrstsets,andwhetheraparseraccepts22013/4/1 Thefunctorlawscanbeveriedbystructuralinduction,simplyapplyingthedenitionsandusingthefunctorlawsforf.instanceFunctorf)Applicative(FreeAf)wherepure=PurePureg*000;y=fmapgy(h:$:x)*000;y=fmapuncurryh:$:((,)$000;x*000;y)InthelastclauseoftheApplicativeinstance,hhastypef(x!y!z),andweneedtoreturnavalueoftypeFreeAfz.Since(:$:)onlyallowsustoexpressapplicationsof1-argumentfunctions,weuncurryhtogetavalueoftypef((x,y)!z),thenweuse(*000;)recursively(seesection8forajusticationofthisrecursivecall)topairxandyintoavalueoftypeFreeAf(x,y),andnallyusethe(:$:)constructortobuildtheresult.Notetheanalogybetweenthedenitionof(*000;)and(++)forlists.3.Applications3.1Example:optionparsers(continued)Byusingourdenitionoffreeapplicative,wecancomposethecommandlineoptionparserexactlyasshowninsection1.2inthedenitionofuserP.Thesmartconstructoronewhichliftsanoption(afunctorrepresentingabasicoperationofourembeddedlanguage)toaterminourlanguagecannowbeimplementedasfollows:one::Optiona!FreeAOptionaoneopt=fmapconstopt:$:Pure()Insection7wegeneralizeonetoanyfunctorandbyusinggenericfunctionsspeciedaspartoftheadjunctionwedenefunctionswhichmakeuseofthefactthatitispossibletostaticallyanalyseaparserdenition:functionsaregivenforlistingallpossibleoptionsandforparsingalistofcommandlineargumentsgiveninarbitraryorder.3.2Example:limitedIO(continued)Insection1.3weshowedanembeddedDSLforlesystemopera-tionsbasedonfreemonadsdoesnotsupportcertainkindsofstaticanalysis.However,wecannowremedythisbyusingafreeapplicative,overthesamefunctorFileSystem.Infact,thecountfunctionisnowdenableforFreeAFileSystema.Moreover,thisisnotlimitedtothisparticularexample:itispossibletodenecountforthefreeapplicativeoveranyfunctor.count::FreeAfa!Intcount(Pure )=0count( :$:u)=1+countuOfcourse,theextrapowercomesatacost.Namely,theexpressivityofthecorrespondingembeddedlanguageisseverelyreduced.UsingFreeAFileSystem,thelesonwhichreadandwriteop-erationsareperformedmustbeknowninadvance,aswellasthecontentthatisgoingtobewritten.Inparticular,whatonewritestoalecannotdependonwhathasbeenpreviouslyread,sooperationslikecopycannotbeimple-mented.3.3SummaryofexamplesApplicativefunctorsareusefulfordescribingcertainkindsofef-fectfulcomputations.ThefreeapplicativeconstructoveragivenfunctorspecifyingthebasicoperationsofanembeddedlanguagegivesrisetotermsoftheembeddedDSLbuiltbyapplicativeoper-ators.Thesetermsareonlycapableofrepresentingacertainkindofeffectfulcomputationwhichcanbedescribedbestwiththehelpoftheleft-parenthesisedcanonicalform:apurefunctionappliedtoeffectfularguments.Thecalculationoftheargumentsmayin-volveeffectsbutintheendtheargumentsarecomposedbyapurefunction,whichmeansthattheeffectsperformedarexedwhenspecifyingtheapplicativeexpression.InthecaseoftheoptionparserexampleuserP,thepurefunctionisgivenbytheUserconstructorandthebasicoperationOptionisdeninganoption.TheeffectsperformeddependonhowanevaluatorisdenedoveranexpressionoftypeFreeAOptionaandtheorderofeffectscandependontheimplementationoftheevaluator.Forexample,ifonedenesanembeddedlanguageforqueryingadatabase,andconstructsapplicativeexpressionsusingFreeA,onemightanalyzetheapplicativeexpressionandcollectinformationontheindividualdatabasequeriesbydeningfunctionssimilartothecountfunctioninthelimitedIOexample.Then,different,possiblyexpensiveduplicatequeriescanbemergedandperformedatonceinsteadofexecutingtheeffectfulcomputationsonebyone.Byrestrictingtheexpressivityofourlanguagewegainfreedomindeninghowtheevaluatorworks.OnemightdenepartsofanexpressioninanembeddedDSLusingtheusualfreemonadconstruction,otherpartsusingFreeAandcomposethembyliftingthefreeapplicativeexpressiontothefreemonadusingthefollowingfunction:liftA2M::Functorf)FreeAfa!FreefaliftA2M(Purex)=ReturnxliftA2M(h:$:x)=Free(fmap(f!fmapf(liftA2Mx))h)Inthepartsoftheexpressiondenedusingthefreemonadcon-struction,theorderofeffectsisxedandtheeffectsperformedcandependontheresultofpreviouseffectfulcomputations,whilethefreeapplicativepartshaveaxedstructurewitheffectsnotde-pendingoneachother.Themonadicpartsofthecomputationcandependontheresultofstaticanalysiscarriedoutovertheapplica-tivepart:test::FreeAFileSystemInt!FreeFileSystem()testop=do:::letn=countop--resultofstaticanalysisn0 liftA2Mop--resultofapplicativecomputationmax read"max"when(maxn+n0)$write"/tmp/test""blah":::Thepossibilityofusingtheresultsofstaticanalysisinsteadoftheneedofspecifyingthembyhand(inourexample,thiswouldac-counttocountingcertainfunctioncallsinanexpressionbylookingatthecode)canmaketheprogramlessredundant.4.ParametricityInordertoproveanythingaboutourfreeapplicativeconstruction,weneedtomakeanimportantobservationaboutitsdenition.The(:$:)constructorisdenedusinganexistentialtypeb,anditisclearintuitivelythatthereisnoway,givenavalueoftheformg:$:x,tomakeuseofthetypebhiddeninit.Morespecically,anyfunctiononFreeAfamustbedenedpolymorphicallyoverallpossibletypesbwhichcouldbeusedfortheexistentiallyquantiedvariableinthedenitionof(:$:).Tomakethisintuitionprecise,weappealtothenotionofrelationalparametricity([11],[14]),which,specialisedtothe(:$:)con-structor,impliesthat:(:$:)::8b.f(b!a)!(FreeAfb!FreeAfa)42013/4/1 Proof.Properties4and6arestraightforwardtoverifyusingthefactthatFreeAfisafunctor,whileproperties5and7followfromlemmas2and3respectively. 7.FreeAasaLeftadjointWenowwanttoshowthatFreeAfisreallythefreeapplicativefunctoronf.Forthat,weneedtodeneacategoryofapplicativefunctorsA,andshowthatFreeAisafunctorFreeA:F!A;whereFisthecategoryofendofunctorsofHask,andthatFreeAisleftadjointtotheforgetfulfunctorA!F.Denition1.Letfandgbetwoapplicativefunctors.Anapplica-tivenaturaltransformationbetweenfandgisapolymorphicfunc-tiont::8a.fa!gasatisfyingthefollowinglaws:t(purex)purex(8)t(h*000;x)th*000;tx:(9)Wedenethetypeofallapplicativenaturaltransformationsbe-tweenfandg,wewrite,inHaskell,typeAppNatfg=8a.fa!gawherethelawsareimplied.Similarly,foranypairoffunctorsfandg,wedenetypeNatfg=8a.fa!gaforthetypeofnaturaltransformationsbetweenfandg.Notethat,byparametricity,polymorphicfunctionsareautomati-callynaturaltransformationsinthecategoricalsense,i.e,forallt::Natfgh::a!bx::fa;t(fmaphx)fmaph(tx):Itisclearthatapplicativefunctors,togetherwithapplicativenaturaltransformations,formacategory,whichwedenotebyA,andsimilarly,functorsandnaturaltransformationsformacategoryF.Proposition3.FreeAdenesafunctorF!A.Proof.WealreadyshowedthatFreeAsendsobjects(functorsinourcase)toapplicativefunctors.WeneedtodenetheactionofFreeAonmorphisms(whicharenaturaltransformationsinourcase):liftT::(Functorf,Functorg))Natfg!AppNat(FreeAf)(FreeAg)liftT (Purex)=PurexliftTk(h:$:x)=kh:$:liftTkxFirstweverifythatliftTkisanapplicativenaturaltransformationi.e.itsatiseslaws8and9.Weuseequationalreasoningforprovinglaw8:liftTk(purex)hdenitionofpureiliftTk(Purex)hdenitionofliftTiPurexhdenitionofpureipurexForlaw9weuseinductiononthesizeoftherstargumentof(*000;)asexplainedinsection8.Thebasecases:liftTk(Pureh*000;Purex)hdenitionof(*000;)iliftTk(fmaph(Purex))hdenitionoffmapiliftTk(Pure(hx))hdenitionofliftTiPure(hx)hdenitionoffmapifmaph(Purex)hdenitionof(*000;)iPureh*000;PurexhdenitionofliftTiliftTk(Pureh)*000;liftTk(Purex)liftTk(Pureh*000;(i:$:x))hdenitionof(*000;)iliftTk(fmaph(i:$:x))hdenitionoffmapiliftTk(fmap(h)i:$:x)hdenitionofliftTik(fmap(h)i):$:liftTkxhkisnaturalifmap(h)(ki):$:liftTkxhdenitionoffmapifmaph(ki:$:liftTkx)hdenitionof(*000;)iPureh*000;(ki:$:liftTkx)hdenitionofliftTiliftTk(Pureh)*000;liftTk(i:$:x)Theinductivecase:liftTk((h:$:x)*000;y)hdenitionof(*000;)iliftTk(fmapuncurryh:$:(fmap(,)x*000;y)hdenitionofliftTik(fmapuncurryh):$:liftTk(fmap(,)x*000;y)hinductivehypothesisik(fmapuncurryh):$:(liftTk(fmap(,)x)*000;liftTky)hliftTkisnaturalik(fmapuncurryh):$:(fmap(,)(liftTkx)*000;liftTky)hkisnaturalifmapuncurry(kh):$:(fmap(,)(liftTkx)*000;liftTky)hdenitionof(*000;)i(kh:$:liftTkx)*000;liftTkyhdenitionofliftTiliftTk(h:$:x)*000;liftTkyNowweneedtoverifythatliftTsatisesthefunctorlawsliftTididliftT(tu)liftTtliftTu:Theproofisastraightforwardstructuralinduction. Wearegoingtoneedthefollowingnaturaltransformation:one::Functorf)Natf(FreeAf)onex=fmapconstx:$:Pure()72013/4/1 casematchOptoptvaluepofNothing!NothingJustp0!runParserp0argsrunParserp[]=parserDefaultprunParser =NothingThematchOptfunctionlooksforoptionsintheparserwhichmatchthegivencommand-lineargument,and,ifsuccessful,returnsamodiedparserwheretheoptionhasbeenreplacedbyapurevalue.Finally,runParsercallsmatchOptwithsuccessivepairsofargu-ments,untilnoargumentsremain,atwhichpointitusesthedefaultvaluesoftheremainingoptionstoconstructaresult.8.TotalityAlltheproofsinthispaperapplytoatotalfragmentofHaskell,andcompletelyignorethepresenceofbottom.Tojustifythevalidityofourresults,then,weneedtoensurethatalldenitionsareactuallypossibleinatotallanguage.Infact,allourADTdenitionscanberegardedasinductivex-pointsofstrictlypositivefunctors,andmostofthefunctiondeni-tionsuseprimitiverecursion,sotheyareobviouslyterminatingforallinputs.Furthermore,mostproofsarecarriedoutbystructuralinduction.Oneexceptionisthedenitionof(*000;):(h:$:x)*000;y=fmapuncurryh:$:((,)$000;x*000;y)whichcontainsarecursivecallwheretherstargument,namely(,)$000;x,isnotstructurallysmallerthantheoriginalone(h:$:x).Toprovethatthisfunctionisneverthelesstotal,weintroduceanotionofsizeforvaluesoftypeFreeAfa:size::FreeAfa!Nsize(Pure )=0size( :$:x)=1+sizexToconcludethatthedenitionof(*000;)isindeedterminating,wejustneedtoshowthatthesizeofargumentfortherecursivecallissmallerthanthesizeoftheoriginalargument,whichisanimmediateconsequenceofthefollowinglemma.Lemma5.Foranyfunctionf::a!bandu::FreeAfa,size(fmapfu)sizeuProof.Byinduction:size(fmapf(Purex))hdenitionoffmapisize(Pure(fx))hdenitionofsizei0hdenitionofsizeisize(Purex)size(fmapf(g:$:x))hdenitionoffmapisize(fmap(f)g:$:x)hdenitionofsizei1+sizexhdenitionofsizeisize(g:$:x) Inmostofourproofsusinginductionwecarryoutinductiononthesizeoftherstargumentof(*000;)wheresizeisdenedbytheabovesizefunction.9.RelatedworkTheideaoffreeapplicativefunctorsisnotentirelynew.TherehavebeenanumberofdifferentdenitionsoffreeapplicativefunctoroveragivenHaskellfunctor,butnoneofthemincludesaproofoftheapplicativelaws.Therstauthorofthispaperpublishedaspecicinstanceofap-plicativefunctorssimilartoourexampleshowninsection1.2([4]).TheexamplewasdevelopedfurtherintheHaskellpackageoptparse-applicative[3].TomEllisproposesadenitionverysimilartoours([6]),butusesaseparateinductivetypeforthecasecorrespondingtoour(:$:)constructor.Hethenobservesthatlaw6probablyholdsbecauseoftheexistentialquantication,butdoesn'tprovideaproof.Wesolvethisproblembyderivingthenecessaryequation1asafreetheorem.Gergo´Erdigivesanothersimilardenition([5]),buthisversionpresentssomeredundancies,andthusfailstoobeytheapplicativelaws.Forexample,Pureid*000;xcaneasilybedistinguishedfromxusingthecountfunctiondenedabove.Thefreepackageonhackage([1])containsadenitionessentiallyidenticaltoourFreeAL,differingonlyintheorderofarguments.Anotherapproach,whichdifferssignicantlyfromtheonepre-sentedinthepaper,underliesthedenitioncontainedinthefree-functorspackageonhackage([2]),andusesaChurch-likeencoding(andtheConstraintKindsGHCextension)togeneral-izetheconstructionofafreeApplicativetoanysuperclassofFunctor.Theideaistousethefactthat,ifafunctorThasaleftadjointF,thenthemonadFTisthecodensitymonadofT(i.e.therightKanextensionofTalongitself).BytakingTtobetheforgetfulfunctorA!F,onecanobtainaformulaforFusingtheexpressionofarightKanextensionasanend.Oneproblemwiththisapproachisthattheapplicativelaws,whichmakeupthedenitionofthecategoryA,areleftimplicitintheuniversalquanticationusedtorepresenttheend.Infact,specializingthecodeinData.Functor.HFreetotheApplicativeconstraint,weget:dataFreeA0fa=FreeA0frunFreeA::8g.Applicativeg)(8x.fx!gx)!gaginstanceFunctorf)Functor(FreeA0f)wherefmaph(FreeA0t)=FreeA0(fmapht)instanceFunctorf)Applicative(FreeA0f)wherepurex=FreeA0(n !purex)FreeA0t1*000;FreeA0t2=FreeA0(u!t1u*000;t2u)Now,forlaw4tohold,forexample,weneedtoprovethatthetermu!pureid*000;tuisequaltot.Thisisstrictlyspeakingfalse,asthosetermscanbedistinguishedbytakinganyfunctorwithanApplicativeinstancethatdoesn'tsatisfylaw4,andastaconstantfunctionreturningacounter-exampleforit.Intuitively,however,thelawsshouldholdprovidedwenevermakeuseofinvalidApplicativeinstances.Tomakethisintuitionpre-cise,onewouldprobablyneedtoextendthelanguagewithquan-ticationoverequations,andproveaparametricityresultforthisextension.AnotherproblemoftheChurchencodingisthatitishardertouse.Infact,thedestructorrunFreeAisessentiallyequivalenttoourraisefunction,whichcanonlybeusedtodeneapplicativenaturaltransformation.AfunctionlikematchOptinsection7.1,whichisnotapplicative,couldnotbedenedoverFreeA0.92013/4/1