September 22, 2011 Tokyo, Japan Haskell’11 Proceedings of the 2011 ACM SIGPLAN Haskell Symposium Sponsored by: ACM SIGPLAN The Association for Computing Machinery 2 Penn Plaza, Suite 701 New York, New York 10121-0701 Copyright © 2011 by the Association for Computing Machinery, Inc. (ACM). Permission to make digital or hard copies of portions of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyright for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permission to republish from: Publications Dept., ACM, Inc. Fax +1 (212) 869-0481 or <[email protected]>. For other copying of articles that carry a code at the bottom of the first or last page, copying is permitted provided that the per-copy fee indicated in the code is paid through the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923. Notice to Past Authors of ACM-Published Articles ACM intends to create a complete electronic archive of all articles and/or other material previously published by ACM. If you have written a work that has been previously published by ACM in any journal or conference proceedings prior to 1978, or any SIG Newsletter at any time, and you do NOT want this work to appear in the ACM Digital Library, please inform [email protected], stating the title of the work, the author(s), and where and when published. ISBN: 978-1-4503-0860-1 Additional copies may be ordered prepaid from: ACM Order Department PO Box 11405 New York, NY 10286-1405 Phone: 1-800-342-6626 (USA and Canada) +1-212-626-0500 (all other countries) Fax: +1-212-944-1318 E-mail: [email protected] ACM Order Number: 565117 Printed in the USA ii Chair’s Welcome It is my great pleasure to welcome all of you to the fourth ACM Haskell Symposium. This meeting is the latest in a long proud line of 11 preceding Haskell Workshops and 3 additional Haskell Symposia. This year, the call for papers generated 28 submissions from all around the globe, of which the program committee selected 11 papers for publication. Each of these has been allotted a 30-minute presentation. We also decided to reintroduce the Future of Haskell discussion. All this should provide us with an exciting program! I would like to first and foremost thank the authors of all submissions for providing us with such a rich set of papers to choose from. Second, the members of the program committee deserve a big thanks for providing high-quality reviews in a very short time and also for passionately contributing to the discussions which led to our final choices. Last but not least, I would like to thank the external subreviewers, many of whom even stayed loyally on call during this entire process. Let the presentations begin! Koen Claessen Haskell’11 Program Chair Chalmers University of Technology, Sweden iii Table of Contents Haskell Symposium 2011 Organization..............................................................................................vi Session 1: Monads Session Chair: Graham Hutton (University of Nottingham) Extending Monads with Pattern Matching.................................................................................................1 Tomas Petricek (University of Cambridge), Alan Mycroft (University of Cambridge), Don Syme (Microsoft Research Cambridge) Bringing Back Monad Comprehensions....................................................................................................13 George Giorgidze, Torsten Grust, Nils Schweinsberg, Jeroen Weijers (Eberhard Karls Universität Tübingen) Session 2: Libraries Session Chair: Ralf Hinze (Oxford University) Termination Combinators Forever............................................................................................................23 Maximilian Bolingbroke (University of Cambridge), Simon Peyton Jones, Dimitrios Vytiniotis (Microsoft Research Cambridge) Hobbits for Haskell: A Library for Higher-Order Encodings in Functional Programming Languages...............................35 Edwin Westbrook (Rice University), Nicolas Frisby (University of Kansas), Paul Brauner (Rice University) A Library Writer’s Guide to Shortcut Fusion..........................................................................................47 Thomas Harper (University of Oxford) Session 3: Parallelism Session Chair: Sam Lindley (University of Edinburgh) Efficient Parallel Stencil Convolution in Haskell......................................................................................59 Ben Lippmeier, Gabriele Keller (University of New South Wales) A Monad for Deterministic Parallelism.....................................................................................................71 Simon Marlow (Microsoft Research Ltd.), Ryan Newton (Intel), Simon Peyton Jones (Microsoft Research Ltd.) Prettier Concurrency: Purely Functional Concurrent Revisions...........................................................83 Daan Leijen, Sebastian Burckhardt, Manuel Fahndrich (Microsoft Research) Session 4: Embedded Languages Session Chair: Neil Mitchell (Standard Chartered) Flexible Dynamic Information Flow Control in Haskell..........................................................................95 Deian Stefan (Stanford University), Alejandro Russo (Chalmers University of Technology), John C. Mitchell, David Mazières (Stanford University) Embedded Parser Generators...................................................................................................................107 Jonas Duregård, Patrik Jansson (Chalmers University of Technology and University of Gothenburg) Towards Haskell in the Cloud...................................................................................................................118 Jeff Epstein (University of Cambridge), Andrew P. Black (Portland State University), Simon Peyton-Jones (Microsoft Research, Cambridge) Author Index................................................................................................................................................130 v Haskell Symposium 2011 Organization Chair: Koen Claessen (Chalmers University of Technology) Program Committee: Conal Elliott (LambdaPix) Andy Gill (University of Kansas) Ralf Hinze (Oxford University) Graham Hutton (University of Nottingham) John Launchbury (Galois, Inc.) Sam Lindley (University of Edinburgh) Rita Loogen (Philipps-Universität Marburg) Neil Mitchell (Standard Chartered) Matthew Naylor (University of York) Bruno Oliveira (Seoul National University) Dimitrios Vytiniotis (Microsoft Research) Steve Zdancewic (University of Pennsylvania) Additional reviewers: Thorsten Altenkirch Nicolas Pouillard Robert Atkey Jason Reich Brian Campbell Robert Rothenberg James Cheney Colin Runciman Mischa Dieterle Alejandro Russo Thomas Horstmeyer Tom Schrijvers Daniel James Nick Smallbone Oleg Lobachev Josef Svenningsson Conor McBride Horstmeyer Thomas Johan Nordlander Simon Thompson Ulf Norell Meng Wang Simon Peyton Jones Stephanie Weirich Sponsor: vi Extending Monads with Pattern Matching TomasPetricek AlanMycroft DonSyme UniversityofCambridge MicrosoftResearchCambridge {tomas.petricek, am}@cl.cam.ac.uk [email protected] Abstract manymonadiccomputationswithanadditionalexpressivepower that goes beyond sequencing. We presented an earlier form of Sequencingofeffectfulcomputationscanbeneatlycapturedusing joinads in F#[27]. This paper makes several novel findings, but monadsandelegantlywrittenusingdonotation.Inpracticesuch ourfirstcontributiontoHaskellissimilartotheearlierworkinF#: monads often allow additional ways of composing computations, whichhavetobewrittenexplicitlyusingcombinators. • Weaddlanguagesupportforimportantkindsofcomputations, We identify joinads, an abstract notion of computation that is includingparallel,concurrentandreactiveprogramming.This strongerthanmonadsandcapturesmanysuchad-hocextensions. is done via a lightweight, reusable language extension that Inparticular,joinadsaremonadswiththreeadditionaloperations: buildsoncorefunctionalconceptssuchaspatternmatching. oneoftypem a → m b → m (a,b)capturesvariousformsof parallel composition, one of type m a → m a → m a that is Thispapersimplifiestheconceptofjoinadandrequiresthatevery inspiredbychoiceandoneoftypem a →m (m a)thatcaptures joinad is also a monad (just like every group is also a monoid). aliasing of computations. Algebraically, the first two operations InHaskell,wealsorelateseveralideasthatalreadydisconnectedly formanear-semiringwithcommutativemultiplication. exist.Thespecificnewcontributionsofthispaperare: Weintroducedocasenotationthatcanbeviewedasamonadic • WepresentdocasenotationforHaskell1 (Sections2,4)that versionofcase.Joinadlawsimplyvarioussyntacticequivalences allowsprogrammingwithmonadiccomputationsextendedwith of programs written using docase that are analogous to equiva- aliasing, parallel composition and choice. We specify laws lencesaboutcase.Examplesofjoinadsthatbenefitfromthenota- about these operations to guarantee that docase keeps the tionincludespeculativeparallelism,waitingforacombinationof familiarsemanticsofpatternmatchingusingcase(Section5). userinterfaceevents,butalsoencodingofvalidationrulesusingthe intersectionofparsers. • To demonstrate the usefulness of the extension, we consider parsing(Section3.1),GUIprogrammingusingevents(Section CategoriesandSubjectDescriptors D.3.3[LanguageConstructs 3.2), lightweight concurrency (Section 3.4), and a parallelism andFeatures]:Controlstructures; F.1.2[ModelsofComputation]: monadwithsupportforspeculativeparallelism(Section3.3). Parallelismandconcurrency • The type of the above computations is captured by a Joinad GeneralTerms Languages,Theory type class (Section 4.2). It relates type classes that have been alreadyproposedforHaskell.Basedonourexperience,wepro- 1. Introduction poseanddiscussseveraladjustmentstotheHaskellbaselibrary Monadsaretraditionallyusedforembeddingsequentialcomputa- andlawsrequiredbythetypeclasseswecombine(Section8). tionsinto lazyfunctionalcode, butmanyrecent usesgowell be- • Ajoinadisanabstractcomputationthatextendsmonadswith yondsequencingofstateorcomputations.Monadshavebeenused threeoperations.Derivingthelawsaboutthethreeoperations for the exact opposite—to explicitly specify parallelism. This is (Section6)revealsthattwooftheoperationsformanalgebraic done by taking a core sequential monad and adding combinators structureknownasanear-semiring. thatincreasetheexpressivepowerbeyondsequencing. Monadsforconcurrent[5]andparallelprogramming[15]sup- The following section demonstrates the usefulness of docase in port forking and synchronizing computations [4]. A monad for thecontextofparallelprogramming. user-interface programming includes combinators for merging events from various sources [29]. These ad-hoc extensions are 2. Motivatingexample extremely useful, but they are not uniform. Developers have to Considerthefollowingproblem:wearegivenatreewithvaluesin understand different combinators for every computation and they leavesandwewanttotestwhetherapredicateholdsforallvalues losethesyntacticsupportprovidedbydonotation. inthetree.Thiscanbeimplementedasarecursivefunction: This paper discusses joinads—an abstract notion of computa- tionsthatextendsmonads.Joinadscaptureapatternthatappearsin all::(a →Bool)→Tree a →Bool all p (Leaf v) =p v all p (Node left right)=all p left ∧all p right Theexecutionofthetworecursivecallscouldproceedinparallel. Permissiontomakedigitalorhardcopiesofallorpartofthisworkforpersonalor Moreover,whenoneofthebranchescompletesreturningFalse,it classroomuseisgrantedwithoutfeeprovidedthatcopiesarenotmadeordistributed forprofitorcommercialadvantageandthatcopiesbearthisnoticeandthefullcitation isnotnecessarytowaitforthecompletionoftheotherbranchas onthefirstpage.Tocopyotherwise,torepublish,topostonserversortoredistribute theoverallresultmustbeFalse. tolists,requirespriorspecificpermissionand/orafee. Haskell’11, September22,2011,Tokyo,Japan. 1Prototype version is available at http://github.com/tpetricek/ Copyright(cid:13)c 2011ACM978-1-4503-0860-1/11/09...$10.00 Haskell.JoinadsandweplantosubmitaGHCpatchinthefuture. 1 Runningtwobranchesinparallelcanbespecifiedeasilyusing instanceMonadZip Parser where strategies [21, 32], but adding short-circuiting behaviour is chal- mzip (P p1)(P p2)=P (λinp → lenging.Usingthedocasenotationandamonadforparallelpro- [((a,b),num1,tail1)| gramming,theproblemcanbesolvedasfollows: (a,num1,tail1)←p1 inp, all::(a →Bool)→Tree a →Par Bool (b,num2,tail2)←p2 inp,num1 ≡num2]) all p (Leaf v) =return (p v) all p (Node left right)= Figure1. InstanceofMonadZipforparsers docase(all p left,all p right)of (False,?) →return False (?,False) →return False mzip::Parser a →Parser b →Parser (a,b) (allL,allR)→return (allL∧allR) Judgingbythetype,themzip operationcouldbeimplementedin Thefunctionbuildsacomputationannotatedwithhintsthatspecify termsof>>=andreturn.Thisimplementationwouldnot,ingen- howtoevaluateitinparallelusingthePar monad[15]extended eral,obeythelawswerequire.WegivemoredetailsinSection6.1. withthesupportfornon-deterministicchoiceoperator[26]. Forparsers,themzipoperationparsestheinputusingbothparsers Toprocesssub-treesinparallel,thesnippetconstructstwocom- andthenreturnsallcombinationofvaluessuchthatthetwoparsers putations (of type Par Bool) and uses them as arguments of consumed the same number of input characters. The meaning of docase.Patternsinthealternativescorrespondtoindividualcom- this operation is that it creates a parser for a language that is an putations.Aspecialpattern?denotesthatavalueofthemonadic intersectionoflanguagesdescribedbythetwoparsers. computationdoesnothavetobeavailableforthealternativetobe Thisimplementationofmzip forparsersisshowninFigure1. selected. When the processing of the left subtree completes and It applies the two parsing functions to the same input and then returnsFalse,thefirstalternativecanbeselectedimmediately,be- returnsallcombinationsforwhichthepredicatenum1 ≡ num2 causetheresultofthesecondcomputationisnotrequired. holds.Analternativeimplementationcouldcomparethetails,but If the result of the left subtree is True and the right one has thatwouldbeinefficientandwouldnotworkforinfiniteinputs. not completed, none of the alternatives are immeriately enabled. ThefunctionbelongstotheMonadZiptypeclassthathasbeen Aftertherightsubtreeisprocessed,oneofthelasttwoalternatives addedtoGHCaspartofarecentimplementationofmonadcompre- can be selected. The choice operator added to the Par monad is hensions.Monadcomprehensions[36]generalizelistcomprehen- non-deterministic,sotheprogrammerneedstoprovidealternative sionstoworkwithanarbitrarymonad.Therecentextension[1,9] clausesthatproducethesameresultincaseofrace.Wereturnto alsogeneralizesgroupingandordering[16]andsyntaxforzipping thistopicinSection3.3,butitis,thecaseintheaboveexample. (zip comprehensions), hence the name mzip. To demonstrate the The selection between alternative clauses is done using the parallelbetweendocaseandgeneralizedmonadcomprehensions, choice operator. Note that the result of each computation is used westartwithanexamplewrittenusingbothnotations. in two independent alternatives. Evaluating the argument repeat- edlywoulddefeatthepurposeofdocase,sothetranslationuses Example. Cambridge telephone numbers can be specified as thealiasingoperatortoavoidthis.Thethirdalternativecombines stringssatisfyingthreeindependentrules:theyconsistof10char- two computations, which is achieved using parallel composition acters,containonlydigitsandtheystartwiththeprefix1223.The operatorprovidedbythePar monad. followingsnippetshowshowtoencodethisruleusingbothparallel The translation of docase is more complex than of the do monadcomprehensionsandthedocasenotation: notation. This is not a bad thing—the notation can be used to writeprogramsthatwouldotherwisebeverycomplex.Intheabove valid =docase(many (sat isDigit), example,developerswouldtypicallywritethesolutioninamore replicateM 10item, imperativestyleshowninAppendixA.Thelengthoftheexplicit startsWith (string "1223")) versionis21linescomparedto6lineintheversionabove. of (num, , )→return num valid =[num |num ←many (sat isDigit) 3. Introducingdocase | ←replicateM 10item This section introduces docase using four examples. We first | ←startsWith (string "1223")] considerdocaseexpressionswithasinglealternativethatcanbe Thethreeargumentsofthedocaseconstructarecombinedusing alsowrittenusingzipcomprehensions[9]andthengraduallyadd themzip function.Inzipcomprehensions,thesameroleisplayed remainingfeatures.AformaldefinitionisshowninSection4. by the bar symbol. If the parsers succeed, they return the same string,sothesnippetonlyneedstheresultofasingleparser.The 3.1 Parallelcompositionofparsers docasesnippetignoresothervaluesusing patternsinsteadof? Parsersareacommonexampleofmonads.Aparserisafunction: patterns.The?patternisspecialanditspecifiesthatavalueisnot whensuppliedwithaninput,itreturnsaparsedvalueandthere- required, which means that the parser can fail. Conversely, the maining unconsumed input. The following definition largely fol- patternrequirestheparsertosucceed,butthenignoresthevalue. lowstheonebyHuttonandMeijer[30]: Thedocasenotationmakesitpossibletowriteeverythingthat can be written using zip comprehensions in a style similar to do newtypeParser a =P (String →[(a,Int,String)]) notation,butitalsoaddsadditionalexpressivepowerinadifferent Compared to standard parsers, there is one notable difference. In waythangeneralizedmonadcomprehensions. addition to the parsed result and unconsumed input, the result also contains Int value, which denotes the number of consumed Desugaring. The desugaring of docase in the simple case characters. This will be needed later. A parser can be made an shown above is essentially the same as desugaring of parallel instanceofMonadtoallowsequentialcompositionandaninstance monad comprehensions. In the translation, the mzip operation is of MonadPlus to support choice. A more interesting question is, writtenas⊗.Thereasonforthiswillbecomeclearwhenwediscuss whatdoesaparallelcompositionofparsersmean: thealgebraictheorybehindjoinadsinSection7.3. 2 validPhone = unit v =λt →if s ≡t thenJust v elseNothing ((many (sat isDigit) ⊗ times item 10) (cid:74) (cid:75)s a ⊗ b =λt →case( a t, b t)of ⊗ startsWith (string "1223"))>>=λx → s s s casex of ((num, ), )→return num (cid:74) (J(cid:75)ust v1,Just v2)→(cid:74)J(cid:75)ust ((cid:74)v1(cid:75),v2); →Nothing a ⊕ b =λt →case( a t, b t)of Theactualtranslationincludesseveraladditionalfeaturesthatare s s s explainedlater,buttheyhavenoeffectonthemeaning.Theexpres- (cid:74) (J(cid:75)ust v1, )→Just(cid:74)v1(cid:75); ( (cid:74),o(cid:75)2)→o2 sioncombinesallargumentsofdocase(orallparallelgenerators a>>=f =λt →case(last t a )of s s of a comprehension) using the ⊗ operation. The result is a com- (cid:74) (J(cid:75)ust (t ,v ))→ f v t(cid:74); (cid:75) →Nothing binedvalueoftypeParser ((String,String),String).Thisvalue 1 1 (cid:74) 1(cid:75)t1 wherelast 0 =Nothing ispassedasaninputto>>=.Thelambdafunctiondecomposesthe last t sf =casesf t of Just v →Just (t,v) tupleusingoriginalpatternsofthedocasealternative.Inthisex- →last (t−1)sf ample,thepatternneverfails,soothercasesareomitted.Thebody ofthelambdacreatesaparserthatsucceedsandreturnstheparsed validphonenumber. Figure2. Semanticsofimperativestreams Next,consideracasewheredocasehasmultiplealternatives, buteachcontainsonlyasinglebinding(apatternotherthan?). Desugaring. Thedesugaredcodeisshownbelow.Eachalterna- 3.2 Choosingbetweenevents tivebindsonlyonasingleevent,sothetranslationdoesnotusethe mzipoperation.Themorelseoperationisabbreviatedas⊕: The examples in this section are based on the imperative stream monaddevelopedbyScholz[29].Imperativestreamsare“agener- shiftClicks = alizationoftheIOmonadsuitableforsynchronousconcurrentpro- (load>>=λa →fmap (const False)mouseClick) ⊕ gramming”. An imperative stream produces zero or more values (shiftUp>>=λu →fmap (const False)mouseClick) ⊕ andperformsside-effectsatcertain(discrete)times.Ourexample (shiftDown>>=λd →fmap (const True)mouseClick) usesasimplifiedmodelofeventstreamswithtypeEvt a thatdo notallowside-effects. Thetranslatorprocessesalternativesindependentlyandthenmerges Event streams can be viewed as functions that take a time themusing⊕.Theeventstreamcorrespondingtoabindingpattern indicating when they are started and return a list of time value (pattern other than ?) is passed as the first argument to >>=. The pairsrepresentingtheoccurrencesoftheevent.Theyareinstances providedfunctioncontainsthebodyofthealternative.Theexam- of the Monad type class. The return operation creates an event ple is simplified, because patterns in the alternatives do not fail. stream that occurs exactly once at the time when it was started. If pattern matching could fail, the event stream should continue Thebehaviourofthe>>=operationisasfollows:whentheinput behavingaccordingtothelastselectedalternative.Toencodethis eventoccurs,theeventstreamreturnedby>>=startsproducingthe behaviour,thetranslationneedsonemoreextension(Section3.4). occurrencesoftheeventstreamgeneratedbythefunctionpassed Semantics. Showingacompleteimplementationofeventstreams to>>=untilthenextoccurrenceoftheinputevent. is beyond the scope of this article. We present a semantics that InadditiontotheoperationsofMonad,eventstreamscanalso defines the implementation and can be used to verify that the implementamonadicor–elseoperationrepresentingachoice: operations obey joinad laws. The semantics follows the original morelse::Evt a →Evt a →Evt a definition of imperative streams [29]. Instead of using lists, we modeleventoccurrencesasafunctionreturningMaybevalue: Theresultingeventstreamoccurswheneveranyofthetwoargu- mentsoccur.Whenbothoftheargumentsoccuratthesametime, Evt a ::T →Maybe a T thenthereturnedvalueisthevalueproducedbythefirst(left)ar- (cid:74) (cid:75) The time T is a discrete value. When applied to a starting time gument.Asexplainedlater(Section5),thisnaturalleftbiasofthe t ∈ T,thesemanticfunctiongivesapartialfunctionthatreturns operationisrequiredbyalawaboutmorelse. Just v if the event occurs at the specified time. The semantics Example. Assumethattheusercancreateobjectsbyclickingand of Monad operations, ⊗ and also ⊕ is given in Figure 2. The canusetheShiftkeytoswitchbetweentwotypesofobjects.The semanticsof⊗and⊕followasimilarpattern.Atgiventime,they userinterfaceprovideseventstreamsshiftDown andshiftUpthat combineboth,ortaketheleftmostvalueiftherequiredvaluesare occur when Shift is pressed and released; an event stream load available.Finally,theresultofmonadicbind(>>=)behavesasan occurs once when the application starts and mouseClick occurs eventstreamgeneratedbythelastoccurrenceoftheinputevent. eachtimethemousebuttonispressed. Usingthissemanticmodel,wecouldderiveanimplementation ThefollowingsnippetcreatesaneventstreamoftypeEvt Bool usingthetechniquesdevelopedrecentlyforfunctionalreactivepro- thatoccurseachtimeamousebuttonisclicked.Thevaluecarried gramming(FRP)byElliott[6].Comparedtootherapproaches,im- bytheeventisaflagdenotingwhetherShiftwaspressed: perativestreamsgiveasimplemodelbasedjustondiscreteevents, butthedocasenotationcanbealsousedwhenprogrammingwith shiftClicks =docase(load,shiftUp,shiftDown)of continuousvalues. (a,?,?)→fmap (const False)mouseClick (?,u,?)→fmap (const False)mouseClick 3.3 Aliasingparallelcomputations (?,?,d)→fmap (const True)mouseClick Thissectionexplainstheuseofthelastofthethreejoinadopera- When one of the events passed to docase produces a value, the tions:maliaswhichrepresentsaliasingofcomputations.Theoper- resulting event starts producing values generated by one of the ationgivesthemonad(joinad)morecontrolofthecontrol-flowby alternatives(True orFalse whenevermouseisclicked).Eachof abstractingawaycertainaspectoftheevaluationmechanism.The the alternatives matches on a single event stream and ignores the parallelall functioninSection2criticallyreliedonthisfeature,so values of other event streams using the ? pattern. The variables wedemonstratetheproblemusingtheparallelismmonad. boundbythepatternsarenotused,sowecoulduse ,butnaming A value of type Par a represents a computation that can be thevariablesmakestheexampleeasiertofollow. evaluated(usingsomeparallelevaluator)togetavalueoftypea. 3 Equipped with this operation, the desugaring can create an unit v =λt →(t,v) (cid:74) (cid:75) aliased monadic computation for each of the docase arguments mzero =λt →(∞,⊥) andthenusethealiasedcomputationsrepeatedly: (cid:74) (cid:75) a ⊗ b =λt →(max t t ,(v ,v )) 1 2 1 2 calcAlt inp = (cid:74) wher(cid:75)e((t1,v1),(t2,v2))=( a t, b t) malias (calc inp)>>=λc0 → (cid:74) (cid:75) (cid:74) (cid:75) a ⊕ b =λt →(min t t ,v) malias (alt1 inp)>>=λc1 → 1 2 (cid:74) wher(cid:75)e((t ,v ),(t ,v ))=( a t, b t) malias (alt2 inp)>>=λc2 → 1 1 2 2 v |t (cid:54)t =v |othe(cid:74)rw(cid:75)ise(cid:74)=(cid:75)v c0 ⊗ c1 >>=λ(a,b)→return (a,b) ⊕ 1 2 1 2 c0 ⊗ c2 >>=λ(a,b)→return (a,b) a>>=f =λt → b s (cid:74) wher(cid:75)e(s,v)= a(cid:74) (cid:75)t; b =f v This version gives the desired operational behaviour. Each of the (cid:74) (cid:75) threeargumentsofdocaseisstartedexactlyonce(intheimple- malias a =λt →(λt →(max t t ,v)) 2 1 2 mentationofmalias).Thebodyiscomposedusingcomputations (cid:74) where(cid:75)(t ,v)= a t 1 thatmerelyrepresentaliases(usingamutablevariableinternally). (cid:74) (cid:75) In particular, both of the alternatives combined using ⊕ use the Figure3. Semanticsoffutures aliasc0 thatreferstothecalccomputation. Semantics. Todescribetheexamplemoreformally,wepresenta ParallelcomputationsareinstancesofMonad.Thereturn opera- simplesemantics.Itcanbeusedtoverifythatthejoinadlaws(Sec- tioncreatesacomputationthatimmediatelyreturnsand>>=evalu- tion6)holdforthePar a type.Here,acomputationismodelled atestheargumentandthenevaluatestheresultproducedbyacon- asafunctionthattakesatimewhenthecomputationisstartedand tinuation.Theimplementationofmzip forPar a startstwocom- returnsatimewhenitcompletestogetherwiththeresult: putationsinparallelandproducesavaluewhentheybothcomplete; Par a ::T →(T,a) morelserepresentsanon-deterministicchoiceandcompleteswhen (cid:74) (cid:75) thefirstofthetwocomputationsproduceavalue. ThesemanticsisshowninFigure3.OperationsofMonadaswell as ⊗ and ⊕ behave as already informally described. The malias Example. Considersomecalculation,thatusesamainfunction, operation applies the semantic function to a given computation calc, and two alternative heuristic functions, alt1 and alt2. In with the starting time of malias as an argument. The resulting ordertocontinue,weneedtheresultofthemainfunctionandone computation finishes either at the completion time or at the time heuristic.Usingdocase,thiscanbewrittenasfollows: whenitiscreated,whicheverhappenslater. calcAlt inp =docase(calc inp,alt1 inp,alt2 inp)of The semantics does not capture the number of computations (a,b,?)→return (a,b) runninginparallel,soitisonlyusefulforconsideringjoinadlaws. The next section describes a variation where computations have (a,?,c)→return (a,c) side-effects.Inthatcasemaliasbecomesmoreimportant,because Notethatthefirstargumentisboundtoavariablea inbothofthe itavoidsduplicationofside-effects.Forsomemonads,suchasIO, alternatives.Thedesiredoperationalmeaningisthattheexpression themaliasoperationcanbedefinedasfollows: startsallthreecomputationsinparallelandthenwaitsuntilcom- malias op =op>>=return◦return putations required by some alternative complete. Using the logic describedsofar,thesnippetmightbetranslatedasfollows: This definition could be used for any monad, but it would not always give useful behaviour. For example, in Par a, it would calcAlt inp = unnecessarilysequentializeallcomputations. (calc inp) ⊗ (alt1 inp)>>=λ(a,b)→return (a,b) ⊕ (calc inp) ⊗ (alt2 inp)>>=λ(a,c)→return (a,c) Nondeterminism. ThesemanticspresentedinFigure3isdeter- ministic,butinreality,thisisnotthecase.Wecouldaddsmallδto This does not give the required behaviour. The code creates a alloperationsinvolvingtime.Theinterestingcaseisthe⊕opera- computation that starts four tasks – the two alternative heuristics tion,wherethevalue(secondelementofthetuple)dependsonthe andtwoinstancesofthemaincomputation.Eliminatingacommon time.Thismeansthattheoperationintroducesnon-determinism. subexpression calc inp does not solve the problem. The value Tokeepprogramssimpleanddeterministic,wefollowtheap- Par a obtained from calc inp represents a recipe for creating a proach used by Elliott for the unambiguous choice (unamb) op- computation,asopposedtoarunningtask.Whenusedrepeatedly, erator[6].Themorelse operationcanbeusedonlywhenthetwo itstartsanewcomputation. argumentsarecompatible: Desugaring. Togetthedesiredsemantics,weneedsomewayto compatible a b =∀t .(t ≡∞)∨(t ≡∞)∨(v ≡v ) startthecomputationonceandgetanaliasedcomputationthatcan 1 2 1 2 where(t ,v )= a ; (t ,v )= b beusedmultipletimes.Thisisexactlywhatthemalias operation 1 1 t 2 2 t (cid:74) (cid:75) (cid:74) (cid:75) provides.Itcanbebestexplainedbylookingatthetypesignature When started at the same arbitrary time, the two operations are togetherwiththeimplementationforthePar amonad: required to produce the same value if they both complete. As discussedinthenextsection,anoperationthatnevercompletescan malias::Par a →Par (Par a) becreatedusingthemzerooperationandrepresentsanalternative malias p =do clause with failing patterns. The condition could be reformulated v ←spawn p in terms of docase alternatives. It is not difficult to see that the return (get v) conditionholdsforthemotivatingexamplefromSection2. The implementation starts a given computation using the spawn 3.4 Committingtoaconcurrentalternative function, which returns a mutable variable that will contain the result of the computation when it completes. Then it returns a Thefinalsimplificationmadeinthepreviousexamplewasthatthe computationoftypePar a createdusingtheget function.When patterns of docase alternatives never failed. This aspect can be used,thecomputationblocksuntilthevariableisset. demonstrated using a monad based on Poor Man’s Concurrency 4 MonaddevelopedbyClaessen[5].AvalueoftypeConcur m a The cases where pattern matching succeeded now contain just a represents a computation that will eventually produce a value of calltoreturn withthebodyofthealternativeasanargumentand typeaandmayproduceeffectsinamonadmalongtheway. the cases where the pattern matching fails contain mzero. This Themonadissimilartoparallelcomputationsfromtheprevious means that the type of values aggregated using ⊕ is m (m a). section.Togiveaconcretesemantics,assumethattheunderlying Additionally,allofthemareeitheroftheformm>>=return◦f or monadisawritermonadusingmonoidM tokeepthestate.The m>>=mzero.Theresultof⊕hasthesametypeasitsarguments,so semanticsfromtheprevioussectioncouldbeextendedbyadding theoverallresultalsohasatypem (m a).Itrepresentsamonadic statetotheresult: value that wraps (or produces) body(ies) that have been selected. Tocreateacomputationthatactuallyrunsthebody,thedesugaring Concur (Writer M)a ::T →(T,a,M) (cid:74) (cid:75) inserts>>=id attheendofthetranslatedexpression. ThesemanticsfromFigure3canbeextendedinastraightforward way to use this function. Unlike Par a, the implementation of 4. Languageextension Concur m a does not actually run computations in parallel. It This section formally defines the docase notation including its emulatesconcurrencybyinterleavingofsteps.Thismeansthatthe syntax,typingrulesandthetranslation. Concur m amonadisdeterministicandthetimeT representsthe numberofprimitivesteps.Inordertosupportpatternsthatmayfail, 4.1 Syntacticextension thetypealsoprovidesanoperationmzerorepresentingafailure: TheextensionaddsanadditionalsyntacticcasetoHaskellexpres- mzero::Concur m a sione.Italsodefinesacategoryofdocasealternativesaanddocase The operation is defined for standard monads that implement the patternswthatincludetheadditionalspecialpattern?(ignore): MonadPlus type class. For the Poor Man’s Concurrency monad, p =x |(p ,...,p )|... Ordinarypatterns 1 n theoperationcreatesacomputationthatneverproducesavalue. w = ? Monadicignorepattern Example Consider a function that concurrently downloads data | p Monadicbindingpattern from two servers. When some data is not available, the function a =(w ,...,w )→e Docasealternative(∃i:w (cid:54)=?) returnsNothing.Whenbothserversproduceavalue,thefunction 1 n i returns Just containing a tuple, but only when the values are e =docase(e1,...,en)of Docaseexpressionwith compatible.Whendataisincompatible,thefunctionshouldfail. a1;...;ak kalternatives(k(cid:62)1) downloadBoth::Concur IO Bool The docase expression is similar to standard case. A docase downloadBoth =docase(dl1,dl2)of pattern w can be standard Haskell patterns p or a special ignore (Just a,Just b)→do pattern written as ?. A docase alternative a must contain at least lift (print "Got both values") onebindingpattern(patternotherthan?),becausethereisnoeasy if compatible a b thenreturn Just (a,b)elsemzero waytoconstructmonadiccomputationthatsucceedswhenallother computationsfail.Finally,thedocaseexpressionmustincludeat ( , )→do leastonealternative. lift (print "Some value missing") return Nothing 4.2 Joinadtypeclass The first alternative of docase matches when both of the com- Thedocasesyntaxoperatesonvaluesofsometypem athatisan putationsproduceJust value.Thebodyprintsamessage(thelift instanceofaJoinadtypeclass.Thetypeclassprovidesoperations functionliftsavalueIO a intoConcur IO a)andthenreturns requiredbythedocasetranslation.Figure4showsthedefinition Just orfailsbyreturningmzero.Thesecondalternativehandles ofJoinad.Thedefinitionjustcombinesseveralclassesthatalready anyvaluesandreturnsNothing afterprintingamessage. existinvariousHaskellextensionsandpackages. Tullsen[33]suggestedreturningmzerowhenpatternmatching fails.Whenitsucceeds,theoriginalbodyisreturned.Forsimplic- • MonadZeroandMonadOraredefinedinaMonadPlusreform ity,weomitmalias: proposal [11]. It aims to distinguish between cases when the (monoidal)operationisunbiased(MonadPlus)andwhenithas (dl1 ⊗ dl2 >>=λt →caset of aleftbias(MonadOr).Forjoinads,werequireleftbias,butwe (Just a,Just b)→do ... expressthelawslightlydifferently(Section6.2). →mzero) ⊕ • MonadZip is defined by a GHC extension that adds monad (dl1 ⊗ dl2 >>=λt →do ...) comprehensions [1, 9]. The extension adds new expressive An intuitive expectation about pattern matching that we want to power that is not available with the do notation [25]. The keepforjoinadsisthat→behavesasacommitpoint.Onceargu- docasesyntaxusestheMonadZiptypeclassinasimilarway mentsmatchpatternsofsomealternative,thecodewillexecutethis asparallelmonadcomprehensionandprovidessimilarexpres- alternativeandnotanyother.However,thisisnotthecasewiththe sivityusingasyntaxsimilartothedonotation. desugaringabove.Whenthefunctiondownloadstwoincompatible • MonadAlias is similar to the Extend type class from the values,itprints“Gotbothvalues”.Thenitfailsandstartsexecuting comonadpackage[18].Theonlydifferenceisthatwerequire thesecondclause,printing“Somevaluesmissing”. thetypetoalsobeamonad. Desugaring To get the desired behaviour, the desugaring needs Thetheoreticalbackgroundandthelawsthatarerequiredtohold toaddanadditionallevelofwrapping.Insteadofjustreturningthe about the operations are discussed in Sections 5 and 7. The next body,wewrapthebodyusingreturn: twosectionscompletethespecificationofthelanguageextension. (dl1 ⊗ dl2 >>=λt →caset of (Just a,Just b)→return (do ...) 4.3 Typingrules →mzero) ⊕ Similarly to other syntactic sugar in Haskell [16], the docase (dl1 ⊗ dl2 >>=λt → expressionistype-checkedbeforetranslation.Thetypingrulesare return (do ...))>>=id showninFigure5andaredefinedintermsofthreejudgements. 5