How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional...

23
See discussions, stats, and author profiles for this publication at: https://www.researchgate.net/publication/282840927 How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44 3 authors, including: Some of the authors of this publication are also working on these related projects: PROWESS View project John Hughes Chalmers University of Technology 130 PUBLICATIONS 4,706 CITATIONS SEE PROFILE Meng Wang University of Kent 31 PUBLICATIONS 200 CITATIONS SEE PROFILE All content following this page was uploaded by Meng Wang on 25 November 2016. The user has requested enhancement of the downloaded file. All in-text references underlined in blue are added to the original document and are linked to publications on ResearchGate, letting you access and read them immediately.

Transcript of How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional...

Page 1: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

Seediscussions,stats,andauthorprofilesforthispublicationat:https://www.researchgate.net/publication/282840927

Howfunctionalprogrammingmattered

Article·July2015

DOI:10.1093/nsr/nwv042

CITATIONS

5

READS

44

3authors,including:

Someoftheauthorsofthispublicationarealsoworkingontheserelatedprojects:

PROWESSViewproject

JohnHughes

ChalmersUniversityofTechnology

130PUBLICATIONS4,706CITATIONS

SEEPROFILE

MengWang

UniversityofKent

31PUBLICATIONS200CITATIONS

SEEPROFILE

AllcontentfollowingthispagewasuploadedbyMengWangon25November2016.

Theuserhasrequestedenhancementofthedownloadedfile.Allin-textreferencesunderlinedinblueareaddedtotheoriginaldocument

andarelinkedtopublicationsonResearchGate,lettingyouaccessandreadthemimmediately.

Page 2: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW National Science Review00: 1–22, 2015

doi: 10.1093/nsr/nwv042Advance access publication 13 July 2015

COMPUTER SCIENCE

How functional programming matteredZhenjiang Hu1,2,∗, John Hughes3 and Meng Wang4

1National Institute ofInformatics, 2-1-2Hitotsubashi,Chiyoda-ku, Tokyo101-8430, Japan;2Department ofInformatics,SOKENDAI (GraduateUniversity forAdvanced Studies),2-1-2 Hitotsubashi,Chiyoda-ku, Tokyo101-8430, Japan;3Department ofComputer Science andEngineering, ChalmersUniversity ofTechnology, SE-412 96Gothenburg, Swedenand 4School ofComputing, Universityof Kent, Canterbury,Kent CT2 7NZ, UK

∗Correspondingauthor. E-mail:[email protected]

Received 18 May2015; Revised 26June 2015; Accepted1 July 2015

ABSTRACTIn 1989 when functional programming was still considered a niche topic, Hughes wrote a visionary paperarguing convincingly ‘why functional programming matters’. More than two decades have passed. Hasfunctional programming really mattered? Our answer is a resounding ‘Yes!’. Functional programming isnow at the forefront of a new generation of programming technologies, and enjoying increasing popularityand influence. In this paper, we review the impact of functional programming, focusing on how it haschanged the way we may construct programs, the way we may verify programs, and fundamentally the waywe may think about programs.

Keywords: functional programming, functional languages, equational reasoning,monad, high orderfunction

INTRODUCTIONTwenty-five years ago,Hughes published apaper en-titled ‘Why Functional Programming Matters’ [1],which has since becomeone of themost cited papersin the field. Rather than discussing what functionalprogramming isn’t (it has no assignment, no side ef-fects, no explicit prescription of the flow of control),the paper emphasizes what functional programmingis. In particular, it shows that two distinctive func-tional features, namely higher order functions andlazy evaluation, are capable of bringing considerableimprovement in modularity, resulting in crucial ad-vantages in software development.

Twenty-five years on, how has functional pro-gramming mattered? Hughes’s vision has becomemore widely accepted. Mainstream languages suchas C#, C++, and Java scrambled one after an-other to offer dedicated support for lambda expres-sions, enabling programmingwith higher order func-tions. Lazy evaluation has also risen to prominence,with numerous papers on new ways to exploit itsstrengths and to address its shortcomings.

One way to gauge the popularity of functionalprogramming is through its presence at conferencesboth in academia and industry. The ACM Inter-national Conference of Functional Programminggrew to 500 participants in 2014. Developer confer-ences on functional programming abound—such asthe Erlang User Conference/Factory in Stockholm,London and San Francisco, Scala Days and Clojure

West in San Francisco, Lambda Jam in Chicago,Lambda Days in Krakow—all with hundreds of par-ticipants. Functional programming is also well rep-resented nowadays at more general industry confer-ences such as GOTO in Aarhus, Strange Loop in St.Louis, and YOW! in Melbourne, Brisbane and Syd-ney, each with well over 1000 delegates.

Functional languages are also increasinglybeing adopted by industry in the real world(https://wiki.haskell.org/Haskell in industry). Toname a few examples, Facebook uses Haskell tomake news feeds run smoothly; WhatsApp relieson Erlang to run messaging servers, achieving upto 2 million connected users per server; Twitter,LinkedIn, Foursquare, Tumblr, and Klout use Scalato build their core infrastructure for sites. And whilenot using functional languages directly, Google’spopular MapReduce model for cloud computationwas inspired by the map and reduce functionscommonly found in functional programming.

Generally speaking, functional programming is astyle of programming: the main program is a func-tion that is defined in terms of other functions, andthe primary method of computation is the applica-tion of functions to arguments. Unlike traditionalimperativeprogramming,where computation is a se-quence of transitions from states to states, functionalprogramming has no implicit state and places its em-phasis entirely onexpressions (or terms). Functionalprogramming focuses on what is being computed

C©TheAuthor(s) 2015. Published by Oxford University Press on behalf of China Science Publishing &Media Ltd. All rights reserved. For Permissions, please email:[email protected]

National Science Review Advance Access published August 24, 2015

Page 3: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

2 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

rather than how it is being computed, much like theway we define mathematical functions. As a simpleexample, consider a mathematical definition of thefactorial function:

0! = 1(n + 1)! = (n + 1)n!

Its definition in the functional language Haskell [2]has exactly the same structure:

fac 0 = 1fac (n + 1) = (n + 1) ∗ fac n

In contrast,with imperative programming,wewouldconsider a state of (n, s) representing the currentcounter and the partial result, and showhow to com-pute the final result by a sequence of state transitionsfrom the initial state of (x, 1):

n = x;

s = 1;

while (n>0) do {s = s*n

n = n-1;

}

The contrast in style is apparent: functional pro-grams are more declarative and often much shorterthan their imperative counterparts. This is certainlyimportant. Shorter and clearer code leads to im-proved development productivity and higher quality(fewer bugs).

But it is probably a more subtle difference, wellhidden behind the overloaded use of the symbol‘=’, that really sets the two apart. In the impera-tive program, ‘=’ refers to a destructive update, as-signing a new value to the left-hand-side variable,whereas in the functional program ‘=’ means trueequality: fac 0 is equal to 1 in any execution con-text, and can be used interchangeably. This charac-teristic of functional programming (known as refer-ential transparency or purity) has a profound influ-ence on the way programs are constructed and rea-soned about—a topic that will be covered exten-sively in the section entitled ‘Correctness of programconstruction’.

What this toy example does not illustrate is theuse of higher order functions, a powerful abstractionmechanism highlighted in Hughes’s paper [1]. Wewill not repeat themessage here. Instead, we will de-scribe the concept of monads (in the section enti-tled ‘Structuring computation’), a design pattern forstructuring computation that crucially depends onhigher order functions. We will show how monadsare used in developing domain-specific languages(DSLs) and taming side effects. In the section en-titled ‘Parallel and distributed computation’, we re-visit the ideas of purity and higher order functionsin the context of parallel and distributed comput-

ing, again showing the unparalleled advantages thatthey bring. Lastly, in the section entitled ‘Functionalthinking in practice’, we briefly sketch the impact offunctional programming in terms of influence on ed-ucation and other programming languages, and real-world adoption. As a note to readers, this reviewpaper is not intended to systematically teach func-tional programming, nor to comprehensivelydiscussits features and techniques.They canbe found in var-ious textbooks on functional programming [3–5].Rather, we aim to give a broad and yet focusedview on how functional programming has matteredto software development, through showcasing ad-vances in both academia and industry.

Since functional programming is a style, in the-ory one could write functional programs in anylanguage, but of course with vastly differing levelsof effort. We call a language functional if its de-sign encourages or to some extent enforces a func-tional style. Prominent languages in this category in-cludeHaskell [2], Erlang [6],ML [7,8], OCaml [9],F# [10], Lisp [11,12], Scheme [13], Racket [14],Scala [15], and Clojure [16]. In this paper, wemostly use Haskell, because Haskell is not only adominant functional language, but also covers all themost important features of functional programming.

CORRECTNESS OF PROGRAMCONSTRUCTIONToday’s software systems are essential parts of oureveryday lives, and their correctness is becomingever more important; incorrect programs may notonly cause inconvenience, but also endanger life andlimb. A correct program is one that does exactly whatits designers and users intend it to do.

Obvious as it sounds, guaranteeing the correct-ness of programs, or even defining the meaning ofcorrectness, is notoriously difficult. The complex-ity of today’s software systems is often to blame.But the design of many programming languages inuse today—the fundamental tools we use to buildsoftware—does not help either. Programs are ex-pressed as sequences of commands returning a finalresult, but also at the same time updating the over-all state of the system—causing both intended andunintended side effects. State update is just one ofthe many kinds of side effect: programs may throwexceptions, send emails, or even launch missiles asside effects. For ‘convenience’, most languages allowsuch effects to be performed, without warning, any-where in a program.

The result is that in order to specify the completecorrectness of any program, one has to describe thewhole state of the system, and the unlimited possi-bilities of interactingwith the outsideworld—an im-possible task indeed. Just consider the task of testing

Page 4: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 3

part of a software system—perhaps a function calledf. Before f can be executed, the tester must bringthe system into the intended pre-state. After f hasfinished, the tester must check the outcome, whichincludes checking that the system state is as ex-pected. But in general, the system state is only partlyobservable, and even identifying theparts of the statewhichf changed is problematic.Muchof theworkoftesting imperative software consists of setting up theright state beforehand, and observing the final stateafterwards.

Functional programming departs dramaticallyfrom this state of impediment by promoting purity:the result value of an execution depends on noth-ing other than the argument values, and no statemay change as program execution proceeds. Con-sequently, it becomes possible to specify programbehaviours independently of the rest of the system.For example, given a function that reverses a list(where [ ] represents the empty list and++ appendstwo lists), we can state the following set of proper-ties governing the function’s correctness. (As a no-tational convention, we use ‘≡’ to denote semanticequality to avoid confusionwith the use of ‘=’ (func-tiondefinition) and ‘==’ (comparison for structuralequality) in Haskell.)

reverse [ ] ≡ [ ]reverse [x] ≡ [x]reverse (y s ++ xs ) ≡ reverse xs ++ reverse y sreverse (reverse xs ) ≡ xs

As there are neither side effects nor outside influ-ence, these laws (the first three) completely charac-terize the function reverse. Drawing an analogy withsworn testimony, the laws specify ‘the behaviour, thewhole behaviour, and nothing but the behaviour’!The significance of this ability to claim that twoexpressions are equal (in any semantically observ-able way) is that one can now freely replace vari-ables by their values, and in general any expres-sions by their equals—that is, programs are refer-entially transparent. This freedom makes functionalprograms more tractable mathematically than theirconventional counterparts, allowing the use of equa-tional reasoning in the design, construction, andverification of programs.

This is just a toy example, but the underlying ideais far-reaching. Readers who are Linux users mayhave come across xmonad (http://xmonad.org/),a tiling window manager for X11, known for itsstability. xmonad is implemented in Haskell andrelies on heavy use of semi-formal methods andprogram derivation for reliability; window managerproperties (such as the behaviour of window fo-cus) are specified as equational laws, similar to

the ones above, and exploited for testing usingQuickCheck [17].

The holy grail of program correctness is to provethe absence of bugs. A landmark achievement inthis respect is Leroy’s CompCert [18], an optimiz-ing C compiler which is almost entirely proven cor-rect with the Coq proof assistant. Tellingly, whenJohn Regehr tested many C compilers using his ran-dom C program generator CSmith, he found 79bugs in gcc, 202 in LLVM and so on, but only 6in Compcert [19]. The middle-end bugs found inall other compilers were entirely absent from Com-pCert, and as of early 2011, CompCert is the onlycompiler testedwithCsmithwhich lackswrong codeerrors. As in the case of xmonad, the use of purelyfunctional immutable data structures played a cru-cial role in this unprecedented achievement. Thisidea of immutability is also appearing in applicationareas where people might least expect it. Datomic(http://www.datomic.com), a fully transactional,cloud-ready and distributed database, presents theentire database as an immutable value, leveraging im-mutability to achieve strong consistency combinedwith horizontal read scalability.

In the rest of this section, we will see equationalreasoning at work—in formal proofs of programcorrectness, in program testing, and in programoptimization—how to associate algebraic proper-ties to functional forms for program reasoning, howto automatically verify type properties, and how tostructure and develop algebraic properties and lawsfor program derivation.

Equational reasoningWe have already seen the use of equational proper-ties as specifications in the reverse example.Thanks toreferential transparency,we arenotonly able towritethe specifications, but also to reason with them.

Correctness proofsOneway tomake use of these equations is in correct-ness proofs, just as in mathematics. Functional pro-grams are often recursively defined over datatypes,lending themselves well to proofs by structural in-duction. For example, the reverse function we havealready specified via equations can be defined inHaskell as follows:

reverse [ ] = [ ]reverse (x : xs ) = reverse xs ++ [x]

The second equation says that, to reverse a list withthe first element as x and the rest of the list as xs, wereverse xs and append x to the end of it. In fact, thisequation is derivable from the third law for reverse byreplacing ys by [x] and simplifying.

Page 5: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

4 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

Now suppose we wish to prove that the def-inition actually satisfies its specification, say theproperty that reverse is its own inverse: for any finitelist xs,

reverse (reverse xs ) ≡ xs

holds. In order to prove this property for any finitelist xs, it is sufficient to show that (1) it holds whenxs is the empty list [ ], and (2) if it holds for xs, then italso holds for x: xs—this is the induction step. (1) iseasy to show, and (2) can be confirmed as follows:

reverse (reverse (x : xs ))≡ {def. of reverse }

reverse (reverse xs ++ [x])≡ { law: reverse (xs ++ y s ) = reverse y s

++ reverse xs }reverse [x]++ reverse reverse xs

≡ { def. of reverse and inductive hypothesis }(reverse [ ]++ [x])++ xs

≡ { def. of reverse and simplification }x : xs

Here, the law used in the above calculation can alsobe formally proven by induction.

Inductive proof is very commonly used in thefunctional setting as an effective way to verify criticalsoftware systems.The inductive proof of the inverseproperty of reverse has a strong resemblance to thatof the inverse property of complex encoding and de-coding in real practice [20]. More practical applica-tion examples include using the Coq proof assistantfor proving the security properties of the JavaCardplatform [21], certifying an optimizing compiler forC [18], and formally proving computational cryp-tography [22].

Property-based testingEquational properties can also be used for testingfunctional programs. Using the QuickCheck test li-brary [17], properties can be expressed via Haskellfunction definitions. For example, the property ofreverse stated in the previous section can be writtenas

propReverseReverse :: [Integer] → BoolpropReverseReverse xs =reverse (reverse xs) == xs

If the property holds, then the corresponding func-tion should always returnTrue, so QuickCheck gen-erates a large number of random argument valuesand checks that the function returns True for eachone (the type stated for the property is needed totell QuickCheck what kind of test data to generate,namely lists of integers).QuickCheck defines aDSL,embedded in Haskell, for expressing properties in atestable subset of predicate calculus.Quantified vari-

ables, such as xs above, range over ‘sets’ which arerepresented by test data generators, with fine controlover thedistributionof the randomlygenerateddata.

When a test fails, QuickCheck ‘shrinks’ the testcase to a minimal failing example. If we test the fol-lowing (wrong) property,

propReverse :: [Integer] → BoolpropReverse xs = reverse xs == xs

then QuickCheck reports that [0, 1] (or, occasion-ally, [1, 0]) is a counterexample; the shrunk coun-terexample is obtained by searching for ways to sim-plify whatever randomly generated counterexampleis first found. We obtain [0, 1] because at least twoelements are needed to make this property fail, andthey cannot be equal—so [0, 0] is not a counterex-ample. Shrinking is of critical importance to makeproperty-based testing useful; without it, the ‘signal’that causes a test to fail is drowned in the ‘noise’ ofrandomly generated data, and debugging failures isfar more difficult.

Interestingly, this kind of testing finesses Di-jkstra’s famous objection that testing can neverdemonstrate the absence of bugs in software, onlytheir presence. If we test properties that completelyspecify a function—such as the four properties ofreverse stated in the introduction—and if every pos-sible argument is generated with a non-zero prob-ability, then property-based testing will eventuallyfind every possible bug. In practice this isn’t true,since we usually do not have a complete specifica-tion, and we limit the size of generated tests, but inprinciplewe can find any possible bug this way—andin practice, this approach to testing can be very effec-tive, since generated tests can explore scenarios thatno human tester would think to try.

QuickCheck is heavily used in the Haskellcommunity—it is the most heavily used testingpackage, and the 10th most used package of anykind, in the Hackage Haskell package database. Thecore of xmonad, discussed above, is thoroughlytested by simple equational properties on the stateof the window manager, just like those we have dis-cussed. The basic idea has been ported to manyother programming languages—FsCheck for F#,ScalaCheck for Scala, test.check for Clojure, buteven non-functional languages like Go and Java.There is even a commercial version in Erlang, mar-keted byQuviq AB, which adds libraries for definingstatemachinemodels of effectful software [23].Thisversionhasbeenused tofindbugs in anEricssonMe-dia Proxy [24], to track down notorious race condi-tions in the database software supplied with Erlang[25], and to formalize the basic software partof the AutoSAR automotive standard, for use inacceptance testing of vendors’ code for Volvo Cars[26]. In this last project, 3000 pages of standards

Page 6: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 5

documents were formalized as 20 000 lines ofQuickCheck models, and used to find more than200 different defects—many of them defects in thestandard itself. A comparison with conventional testsuites showed that the QuickCheck code was al-most an order of magnitude smaller—despite test-ing more!

Automatic optimizationThe ability to replace expressions with their equalsand be oblivious to the execution order is a hugeadvantage in program optimization. The GlasgowHaskell Compiler (GHC) uses equational rea-soning extensively internally, and also supportsprogrammer-specified rewrite rules (equationaltransformations) as part of the source program (inpragmas) for automatic optimization. For instance,we could give GHC the inverse property of reverseto eliminate unnecessary double reversals of lists,and GHC will then apply the rule whenever it can.(While it is unlikely that a programmer would writea double reversal explicitly, it could well arise duringoptimization as a result of inlining other functioncalls.)

{-# RULES

’’reverse-inv’’ forall xs.

reverse (reverse xs) = xs

#-}

In practice, peoplemake use of this utility for seriousoptimizations. For example, shortcut fusion [27,28]is used to remove unnecessary intermediate datastructures, and tupling transformation [29] is usedto reduce multiple traversals of data.

HERMIT [30] is a powerful toolkit for devel-oping new optimizations by enabling systematicequational reasoning inside theGHC’s optimizationpipeline. It provides a transformationAPI that canbeused to build higher level rewrite tools.

Functional formsHigher order functions are not only useful for ex-pressing programs, they can be helpful in reason-ing and proofs as well. By associating general alge-braic (equational) laws with higher order functions,we can automatically infer properties from theselaws when the higher order functions are applied toproduce specific programs.

Two of the most important higher order func-tions are fold and unfold (also known as catamor-phism and anamorphism). They capture two natu-ral patterns of computation over recursive datatypessuch as lists and trees: unfolds generate data struc-tures and folds consume them. Here, we give themthe name ‘functional forms’—they can be used as

design patterns to solve many computational prob-lems, and these solutions inherit their nice algebraicproperties. In this review, we focus on fold and un-fold on lists. In fact, a single generic definition of foldcan be given for all (algebraic) datatypes [31–33],and dually for unfold.

Algebraic datatypesWe have seen an example of an algebraic datatype,namely List, earlier on in the reverse example. Listis the most commonly used datatype in functionalprogramming—to such an extent that the first func-tional languagewas namedLisp [11], as in ‘LISt Pro-cessing’.A listwhose elements have the typeα canbeconstructed by starting with the empty list Nil, andsuccessively addingelementsof typeα to the list, oneby one, using the data constructor Cons.

data List α = Nil | Cons α (List α)

For instance, the list [1, 2, 3, 4], of type List Int, isrepresented as follows:

as = Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))

The notations [ ] and infix : that we used above aresimply shorthand for applications ofNil andCons—Cons x xs can be written as x : xs. We will alsouse the ‘section notation’ (surrounding an operatorby parentheses) to turn a binary infix operator ⊕into a prefix function: (⊕) a b = (a⊕) b = (⊕b)a= a⊕ b.

FoldFoldr, which consumes a list and produces a value asits result, is defined as follows:

foldr f e Nil = efoldr f e (Cons x xs ) = f x (foldr f e xs )

The effect of foldr f e xs is to take a list xs, and re-turn the result of replacingNil by e and eachCons byf. For example, foldr f e as converts the above list asto the value of

f 1 ( f 2 ( f 3 ( f 4 e)))

This structurally inductive computation patterncaptured by foldr is reusable; by choosing different fsand es, foldr can performa variety of interesting func-tionson lists.To take a fewexamples, sum sumsupallelements of a list, prodmultiples all elements of a list,maxlist returns themaximumelementof a list, reversereverses a list , map f applies function f to everyelement of a list, and inits computes all initialprefix lists of a list. In the definitions below, we usepartial applications of foldr: defining sum asfoldr (+) 0 (with two arguments rather than three)

Page 7: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

6 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

is the same as defining sum xs to be foldr (+) 0 xs.

sum = foldr (+) 0prod = foldr (×) 1maxlist = foldr max (−∞)reverse = foldr f [ ] where f a r = r ++ [a]map g = foldr f [ ] where f a r = g a : rinits = foldr f [[ ]] where f a r = [ ] :

map (a :) r

UnfoldUnfoldr is the dual of foldr, which generates a listfrom a ‘seed’. It is defined as follows:

unfoldr p f g seed =if p seed then [ ]else ( f seed) : unfoldr p f g (g seed)

The functional form unfoldr takes a predicate p indi-catingwhen the seed should unfold to the empty list.When the condition fails to hold, then function f isused to produce a new list element as the head, andg is used to produce a new seed from which the tailof the new list will unfold. Like foldr, unfoldr can beused to define various functions on lists. For exam-ple, we can define the function downfrom n to gen-erate a list of numbers from n down to 1:

downfrom n = unfoldr isZero f g nwhere

isZero n = n == 0f n = ng n = n − 1

Composition of functional formsFoldr and unfoldr can be composed to produce cleardefinitions of computations, which we think of asspecifications in this section, because of their declar-ative nature. For example, the following gives a clearspecification for computing themaximumof all sum-mations of all initial segments of a list:

mis = maxlist ◦ (map sum) ◦ inits

It is defined as a composition of four functions wedefined as foldrs before.

Given the duality of unfold and fold (one gen-erating data structures and the other consumingthem), compositions of an unfold followed by a foldform very interesting patterns, known as hylomor-phisms [32,34,35]. A simple example of a hylomor-phism is the factorial function:

factorial n = prod (down from n)

where prod is defined using foldr and downfromusingunfoldr.

General lawsFunctional forms enjoy many nice laws and proper-ties that can be used to prove properties of programsthat are in those forms. Fold has, among others, thefollowing three important properties [32].

First, foldr has the followinguniquenessproperty:

foldr f1 e1 ≡ foldr f2 e2 ⇔ f1 ≡ f2 ∧ e1 ≡ e2

which means that two foldrs are equivalent (exten-sionally), if and only if their corresponding compo-nents are equivalent. It serves as the basis for con-structing other equational rules.

Second, foldr is equipped with a general fusionrule to deal with composition of foldrs, saying thatcomposition of a function and a foldr can be fusedinto a foldr, under the right conditions.

h ( f a r ) ≡ f ′ a (h r )h ◦ foldr f e ≡ foldr f ′ (h e)

Third,multiple traversals of the same list by differentfoldrs can be tupled into a single foldr, and thus a sin-gle traversal.

h x = (foldr f1 e1 x, foldr f2 e2 x)h = foldr f (e1, e2)

where f a (r1, r2) = ( f1 a r1, f2 a r2)

Let us use a simple example to demonstrate howfusion is useful in the derivation of efficient pro-grams. Assume that we have an implementation ofinsertion sort (into descending order) using foldr:

sort = foldr insert [ ]whereinsert a [ ] = [a]insert a (b : x) = if a ≥ b thena : b : x else b : insert a x

Now suppose that we want to compute the maxi-mum element of a list. This is easy to do using theexisting sorting program:

maxList = hd ◦ sort

where hd is a function to select the first element fromanon-empty list (hd (a : x) = a) and return−∞ ifthe list is empty. Though declarative and obviouslycorrect, this program is inefficient. It is overkill tosort the whole list, just to get the head. Fusion, us-ing the laws above, provides a standard way to solvethis problem.The laws tell us that if we can calculatef ′ such that

∀a, x. hd (insert a x) ≡ f ′ a (hd x)

then we can transform hd ◦ sort tofoldr f ′ (−∞). By instantiating x as b : y and

Page 8: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 7

performing a simple calculation, we obtain f′ asfollows:

f ′ a b ≡ hd (insert a (b : y))≡ if a ≥ b then a else b

Thus, we have derived a definition of maxList usinga single foldr, which is exactly the same as the def-inition in the section entitled ‘Fold’ above. This fu-sion improves the time complexity of maxList fromquadratic in the length of the list to linear.

Aswe have seen, equational reasoning and higherorder functions (functional forms) enjoy a symbi-otic relationship: each makes the other much moreattractive.

TypesWhat is the type of a function like foldr? In the ex-amples above, we have already seen it used with sev-eral different types! Its arguments are a function thatcombines a list element with an accumulator, an ini-tial value for the accumulator, and a list of elementsto be combined—but those list elements may be in-tegers, lists themselves, or indeed any type; the ac-cumulator can likewise be of any type. Being ableto reuse higher order functions like map and foldrfor different types of data is a part of what makesthem so useful: it is an essential feature of functionalprogramming languages. Because of this, early func-tional languages did without a static type checker;they were dynamically typed, but the compiler didnot attempt to discover type errors. Some, likeErlang or Clojure, still are.

Polymorphic typesIn 1978,Milner introduced polymorphic types toML,to solve this problem. The key idea is to allow typesto include type variables, which can be instantiatedto any type at all, provided all the occurrences of thesame variable are instantiated to the same type. Forexample, the type of foldr is

foldr :: (α → β → β) → β → List α → β

where α is the type of the list elements, and β is thetype of the accumulator. When foldr was used to de-fine sum above, then it was used with the type

foldr :: (Integer → Integer → Integer) →Integer → List Integer → Integer

(in which α and β are both instantiated to Integer);when it was used to define sort then its type was

foldr :: (γ → List γ → List γ )

→ List γ → List γ → List γ

(in which α is replaced by γ , the elements in the listto be sorted and β the accumulator type is a list ofthese). This allowed the flexibility of polymorphismtobe combinedwith the security of static type check-ing for the first time. ML also supported type infer-ence: the type of foldr (and indeed, every other func-tion) could be inferred by the compiler from its def-inition, freeing the programmer from the need towrite types in function definitions at all so ML wasas concise and powerful as the untyped languages ofits day,with the addedbenefitof static type checking.

Both these ideas have made a tremendousimpact. Many functional programming languagessince, Haskell among them, have borrowed thesame approach to polymorphic typing that MLpioneered. Java generics, introduced in Java 5, werebased directly on Odersky and Wadler’s adaptionof Milner’s ideas to Java [36]; similar featuresappeared thereafter in C#. Type inference (in amore limited form) appeared in C# 3.0 in 2007, andtype inference is increasingly available in Java too.

In fact, ML’s polymorphic types also give ussurprisingly useful semantic information about thefunctions they describe. For example, the reversefunction can be applied to lists with any type of el-ement, and so has the polymorphic type

reverse :: List α → List α

This implies that it also satisfies

∀f, xs. map f (reverse xs) = reverse (map f xs)

as, indeed, does any other function with the samepolymorphic type!These ‘free theorems’, discoveredbyWadler [37], are an applicationofReynold’spara-metricity[38]; they are used, among other places, tojustify the ‘short cut deforestation’ optimization inthe GHC [27].

Type classes for overloadingHaskell’s major innovation, as far as types are con-cerned, was its treatment of overloading. (Over theyears,many innovationshavebeenmade inHaskell’stype system; herewe refer to innovations in the earlyversions of the language.) For example, the equalityoperator is overloaded inHaskell, allowing program-mers to use different equality tests for different typesof data.This is achieved by declaring an equality typeclass:

class Eq α where(==) :: α → α → Bool

which declares that the equality operator (==) canbe applied to any type α with an instance of the classEq; programmers can define instances of each class,and the compiler infers automaticallywhich instanceshould be used.

Page 9: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

8 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

Right from the start, Haskell allowed instancesto depend on other instances. For example, (struc-tural) equality on lists uses equality on the list ele-ments, expressed in Haskell by defining

instance Eq α ⇒ Eq (List α) wherexs == y s = . . .

That is, given an equality on typeα, the compiler canconstruct an equality on typeList α, using the defini-tion of== in the instance. Or to put it another way,the compiler can reduce a goal to find anEq (List α)instance, to a goal to find an Eq α instance, for anyα. This looks a lot like logic programming! Over theyears, Haskell class and instance declarations havebecome more and more powerful, incorporatingaspects of both logic programming and func-tional programming, with the result that the typechecker is now Turing-complete (Robert Dock-ins, The GHC typechecker is Turing-complete,https://mail.haskell.org/pipermail/haskell/2006-August/018355.html). The important observa-tion here is that Haskell’s class system gives us aprogrammable type checker, which—while it doesnot allow us to accept programs that will generateruntime-type errors—does allow us to constructtype systems for DSLs embedded in Haskell withexquisite precision. Scala’s implicits were directlyinspired by Haskell’s type classes, and allow manyof the same tricks to be played [39].

Types and logicFinally, there is a deep connection between typesand logic. Just consider the type of the apply func-tion:

apply :: (α → β, α) → β

If we read function arrow types as logical implica-tions, and the pair type as a conjunction, then thistype reads as the (true) proposition

((A ⇒ B) ∧ A) ⇒ B

It turns out that this is not a coincidence: we cansoundly regard apply as a proof of this property,and any type which is inhabited by some expression(in a sufficiently carefully designed functional lan-guage) corresponds to a provable property. Proof as-sistants such as Coq [40] and Agda [41] are basedon this correspondence, the Curry–Howard isomor-phism, and enable users to prove theorems by writ-ing programs.A key notionhere is that of a dependenttype, a type which depends on a value. For example,if the List type is parameterized not only on the el-ement type, but also on the length of the list, thenreverse can be given a more informative type:

reverse :: ∀k :: Nat, α :: Set. List k α → List k α

representing the fact that its result has the samelength as its argument. (Here Set is roughly speak-ing ‘the type of types’, or more precisely, the typeof small types, i.e. excluding types such as Set itself.)Predicates can then be represented by types that aresometimes empty. For example, Even k might be atype that is empty if k is odd, and non-empty if k iseven—so constructing a term of type Even k provesthat k is even. Using these ideas, it is possible to con-struct large functional programs with formal proofsof correctness. Perhaps themost impressive exampleto date is CompCert [18], already discussed above.

Algebra of programmingIn the section entitled ‘Functional forms’, we haveseen a useful set of functional forms that capturecommon computation patterns while enjoying gen-eral algebraic laws for program reasoning. This at-tractive idea can be carried much further, lead-ing to the development of many specific theoremsas building blocks for more complex reasoning.The result is the algebra of programming [42,43],where functional programming provides an alge-braic framework for building programming theoriesfor solving various computational problems by pro-gram calculation (derivation)—a systematic way oftransforming specification into efficient implemen-tation through equational reasoning. This supports,in practice, Dijsktra’s argument that programmingshould be considered as a discipline of a mathemati-cal nature [44].

In this section, we review the programming theo-ries that have been developed for constructing pro-grams from specifications, and demonstrate howthese theories can be used to derive programs invarious forms for efficient sequential or parallelcomputation.

Programming: deriving programsfrom specificationsBefore addressing the solution of programmingproblems, consider the following mathematicalproblem known as the Chinese Chicken–Rabbit-Cage Problem:

An unknown number of rabbits and chickens are locked in

a cage. Counting from above, we see there are 35 heads,

and counting from below, there are 94 feet. How many

rabbits and chickens are in the cage?

The degree of difficulty of this problem largely de-pends onwhichmathematical tools one has to hand.A preschool childmay find it very difficult; he has nochoice but to enumerate all possibilities. However, amiddle school student equipped with knowledge of

Page 10: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 9

equation solving should find it easy. He would let xbe the number of chickens and y that of rabbits, andquickly set up the following problem specification:

x + y = 352x + 4y = 94

The rest is entirely straightforward.The theory of lin-ear equations gives us a strategy for solving them sys-tematically, to discover the values of the unknowns(i.e., x= 23, y= 12).

Wewant to solveourprogrammingproblems thisway too! We would like to have an algebra of pro-grams: a concise notation for problem specification,and a set of symbol manipulation rules with whichwe may calculate (derive) programs from specifi-cations by equational reasoning. Here, by ‘specifica-tion’, we mean two things: (1) a naive functionalprogram that expresses a straightforward solutionwhose correctness is obvious; and (2) a program in aspecific form of composition of functional forms. By‘program’, we mean an efficient functional program,which may be sequential, parallel, or distributed.

Programming theoriesJust like the specific laws developed for factorizationin solving equations, many laws (theorems) for de-riving efficient functional programs from specifica-tions have been developed [43,45]. They are usedto capture programming principles by bridging thegap between specifications and their implementingprograms. As an example, many optimization prob-lems can be naively specified in a generate-and-testway: generating all the possibilities, keeping thosethat satisfy the requirements, and returning one thatmaximizes a certain value:

opt = maxlist ◦ map value ◦ filter p ◦ gen

To solve this kind of optimization problems usingfolds, many theorems [43,46] have been developed.One example is: if (1) gen,p, and value canbedefinedas foldrs, and (2) value = foldr (⊕) e , where ⊕ isassociative and max is distributive over ⊕, then optcan be solved in linear time by a functional programin terms of a single foldr. With this theorem, solvingoptimization problems become easy: one just needsto specify the problem in the form described and therest will follow!

Programming theory developmentMany theories for the algebra of programminghave been developed—but new ones can always beadded. There is a general procedure to develop pro-gramming theories consisting of the following threemajor steps [47,48].

(i) Define a specific form of programs, in termsof functional forms and their composition,that can be used to describe a class of inter-esting computations.

(ii) Develop calculational rules (theorems) tobridge the gap between the new specificform and the existing functional forms.

(iii) Developmore theorems that can turnmoregeneral programs into the specific form towiden the application scope.

Thefirst stepplays a very important role in this devel-opment. The specific form defined should not onlybe powerful enough to describe computations of in-terest, but alsomanipulable and suitable for the laterdevelopment of calculational laws.

Systems for program derivationMany systems have been developed for supportingprogram derivation and calculation. Examples areKIDS [49], MAG [50], Yicho [47], and so on. Ingeneral, such tools (1) support interactive develop-ment of programs by equational reasoning so thatusers can focus on their creative steps, (2) guaranteecorrectness of the derived program by automaticallyverifying each calculation step, (3) support devel-opment of new calculation rules so that mechanicalderivation steps can be easily grouped, and (4)makethe development process easy to maintain (i.e. thedevelopment process should be well documented).

Proof assistants and theorem provers can pro-vide a cheapway to implement a system for programreasoning and program calculation [51–53]. For in-stance, with Coq [40], a popular theorem prover,one can use Ltac, a language for programming newtactics, to build a program calculation system [53]:(1) Coq tactics can be used effectively for automaticproving and automatic rewriting, so that tedious cal-culation can be hidden with tactics; (2) new tacticscan coexist with the existing tactics, and a lot of use-ful theories of Coq are ready to use for calculation,and (3) tactics can be used in a trial-and-error man-ner thanks to Coq’s interaction mechanism.

In contrast to deriving functional programs fromformal specifications, MagicHaskeller [54,55] is aninteresting tool that automatically synthesizes func-tional programs from input/output examples. Al-though still under development, it has demonstratedthe feasibility of the idea by synthesizingmany inter-esting Haskell programs from just a small number ofexamples.

STRUCTURING COMPUTATIONIn the previous section, we have experienced theliberating power of the absence of side effects.

Page 11: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

10 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

Referential transparency is the basis of the wealthof properties that enabled us to reason, to test, tooptimize, and ultimately to derive programs. Onthe other hand, functional programmers are by nomeans ascetics withdrawing from worldly pleasures.Functional programs are real programs! They doperform necessary computations with side effectssuch as I/Os, exceptions, non-determinism, etc.

The difference is simply a shift of perspective.Functional programmers view side effects as costly,which shall be used with care, and at the bestavoided. Let us suppose that we have to pay for eachpair of parentheses in a game of writing arithmeticexpressions. Associativity, which removes the needof parenthesizing, becomes very valuable and play-ers will be incentivized to write 3 × 0.5 × 5 insteadof (3÷2)× 5 for example. Programming is like suchwriting of expressions, and the role of a program-ming language is to encourage good practice and atthe same time discourage the opposite.

Pure functional languages do just that: side ef-fects are encoded by a programming pattern knownasmonads [56–59]. Since it is an encoding, purity isnot threatened. But monads do enjoy a clearly dis-tinguished syntax and type to encourage thought-ful design. We will see later in this section in moredetails the idea of monadic effects, and the bene-fit of being disciplined with the uses of them. As amatter of fact, the concept of monads as a program-ming pattern has applications far beyond handlingside effects; it is fundamentally a powerful way ofstructuring computations and has been adopted inlanguages with built-in side effects! To name a few,some readers may have heard of async monad in F#,promises in JavaScript, or future in Scala, which areessentially imitations of amonad used to structuringasynchronous operations. On a different front, Lan-guage INtegratedQuery (LINQ) in .NET is directlyinspired by monads, and a syntax sugar for themknown as monad comprehension (following from setcomprehension) in Haskell.

In the sequel of this section, wewill briefly reviewmonads and demonstrate their uses in structuringcomputations, in the context of programming lan-guage development, which is itself a particularly suc-cessful application of functional programming.

Monadic compositionOriginally as a concept in category theory that wasused by Moggi to modularize the structure of a de-notational semantics [56,57], monads are soon ap-plied by Wadler to the functional implementationsof the semantics that Moggi describes, and as a gen-eral technique for structuring programs [58,59].

A monadM consists of a pair of functions returnand (�=) (pronounced as ‘bind’).

return :: α → M α

(�=) :: M α → (α → M β) → M β

One shall read Mα the type of a computation thatreturns a value of typeα, andperhaps performs someside effects.Ananalogy is to see a valueof typeMα asa bank card and its pin; they are not the same as plaincash a (of type α) which can be used immediately,but contain the instruction of producing an a, and infact any number of as.

We cannot use a value of type Mα directly, butwe can combine it with other instructions that usethe result. For example, consider an evaluator of typeTerm → Environment → M Value , whereM is amonad. The evaluator does not give us a value di-rectly, but we can bind its result to be used in sub-sequent computations:

eval u e �= (λa →eval v e �= λb →return (Num (a + b))

This expression evaluates the two operands of an ad-dition and add them up. The result of the first eval-uation is bound to the variable a and is passed tothe second evaluation, and together with the secondresult (bound to b) they form parts of a new valuewhich is again encapsulated in the monad by return.This pattern of structuring computation is very com-mon and has been giving special syntax support inHaskell [58].The above expression can be rewrittenas the following equivalent form:

do a ← eval u eb ← eval v ereturn (Num (a + b))

which is seemingly similar to the followingexpression:

let a = eval u eb = eval v e

in Num (a + b)Now, let us say we want to extend the evaluator

with error handling as in

eval :: Term → Environment → Maybe Value

data Maybe a = Just a | Nothingwhere failures are represented by Nothing and suc-cessful computations return values wrapped in Just.Without giving up on purity and resorting to a lan-guage with side effects, the non-monadic definitionswhich structure computations with let have to be te-diously rewritten: every let binding now has to bemade toperformacase analysis, separating successes

Page 12: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 11

from failures, and then decides the next step accord-ingly.

Whereas for the monadic version, the story israther different. The structure of the evaluator is in-dependent of the underlying computation that isused, and if carefully designed changing one entailsminimumchanges to theother. In the above, the spe-cializing of monad type M to Maybe links the rightinstances of return and�= (in fact monads forms atype class).

instance Monad Maybe wherereturn x = Just xNothing �= f = NothingJust x �= f = f x

There is no change in the evaluator’s definition, asthe handling of failure is captured as a pattern and lo-calized in the definition of�=. In a similar manner,we can add to the evaluator real-world necessitiessuch as I/Os, states or non-determinism in a similarmanner—simply replacing the underlying monad.

Monads not only encapsulate side effects, butalso make them first class. For example, the functionsequence :: [m α] → m [α], where m is a monad,evaluates each computation in turn, and collects theresults. In the evaluator example, one may rewritethe expression for addition as

liftM sum (sequence [eval u e , eval v e ])

where sum adds up a list of numbers and is lifted (byliftM) to handle monadic values.

In addition to structuring programming lan-guages semantics, monads also offer a nice frame-work for I/Os in a pure language.The idea is to viewI/Ooperations as computations interactingwith the‘outside world’ before returning a value: the outsideworld is the state, which (represented by a dummy‘token’) is passed on to ensure proper sequencing ofI/O actions [60]. For example, a simple Read-Eval-Print Loop that reverses the command line input canbe written with recursion as a function of type IO (),where IO is themonad and () is a singleton typewith() as its only value.

repl :: IO ()r e pl = do

line ← getLineputStrLn (reverse line)repl

Giving the stateful implementationof the IOmonad,it is obvious that it could be used to support mutablestates and arrays [60], though a different approachbased on normal state monad, which encapsulateseffectful computations inside pure functions,may beconsidered better [61,62].

Further extensions of the IO include the han-dling of concurrency [63]. The implementation of

software transactional memory (STM) with mon-ads [64] is a clear demonstration of the benefit ofcarefully managed side effects; twomonads are usedin the implementation: the STM monad structurestentative memory transactions, the IOmonad com-mits the STM actions exposing their effects to othertransactions, and a function atomic connects thetwo:

atomic :: STM α → IO α

As a result of this explicit distinction of different typeof effects made possible by monads, only STM ac-tions and pure computations can be performed in-side a memory transaction ruling out irrevocable ac-tions by construction, and no STM actions can beperformed outside a transaction effectively eliminat-ing a class of bugs altogether. Moreover, since readsfrom and writes to mutable cells are explicit as STMactions, the largenumberof other (guaranteedpure)computations in a transaction are not tracked by theSTM, because they are pure, and never need to berolled back. All these guarantees make a solutionbased on monads very attractive indeed.

Monads are often used in combination. For ex-ample, an evaluator may need to handle errors andat the same time performing I/O, and it will be desir-able to reuse existingmonads insteadof creating spe-cialized ones. The traditional way of achieving suchreuse is through moving up the abstraction level tobuild monad transformers [65,66], which are similarto regularmonads, but insteadof standing alone theymodify the behaviours of underlying monads, effec-tively allowing different monads to stack up. Thedownside of monad transformers is that they are dif-ficult to understand and are fragile to changes. Alter-natives have been proposed and it is still an activearea of research [67–69].

Inspired by monads, other abstract views ofcomputation have emerged, notably arrows [70,71]and applicative functors [72]. First proposed byHughes [70], arrows are more general than monadsallowing notions of computation that may be par-tially static (independent of the input) or may takemultiple inputs. Applicative functors are a proper su-perset of monads, which has weaker properties andthusmoremembers. Similar tomonads, both arrowsand applicative functors can be used for structur-ing the semantics of embedded domain-specific lan-guages (EDSLs) [73,74]. A theoretical comparisonof the three can be found in [75].

Embedded domain-specific languagesSo far, we have only discussed one way of devel-oping languages that is to implement stand-alone

Page 13: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

12 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

compilers or interpreters. Functional programmingis well suited for the task and the use of monad hassignificant impact on modularity. However, the par-ticular success of functional programming actuallycomes from another way of language developmentknown as embedding [76,77].

Languages produced through embedding areknown as embedded languages, which are libraries inhost languages. Giving that such libraries usually fo-cus on providing functionalities of a specific prob-lemdomain, the languages resulting from are seen asEDSLs, while the host languages are usually generalpurpose. The EDSL and its host language are one:the API of the library specifies a set of constructs ofthe newDSL, which at the same time shares the toolchain and the generic features of the host language,such as modules, interfaces, abstract data types, orhigher order functions. Moreover, the EDSL imple-mentation is very ‘lightweight’—the EDSL designercan add features just by implementing a new func-tion in the library, and can easily move functionalitybetween the EDSL library and its clients. The easeof experimentation with such an EDSL helps imple-mentors fine-tune the design, and enables (some)end users to customize the implementation withdomain-specific optimizations.

SuchEDSLs have appeared in awide spectrumofapplication areas, including compiler development,database queries, web applications, GUIs,music, an-imations, parallelism, hardware descriptions, imageprocessing, workflow, and more. See Fig. 1 for a fewexamples and [78] for a comprehensive listing.

We have said that EDSLs are libraries. But obvi-ously not all libraries are languages. So what is it thatelevates EDSLs from their humble origin as librariesto the level of languages?

For a language to be worth its name, it must al-low code fragments manipulating primitive data tobe shared through defining reusable procedures. Inan EDSL setting, the data (also known as the do-main concepts) are themselves functions. For exam-ple, in modelling 3D animation, the domain con-cept of behaviour, representing time-varying reactivevalues, is a function from time to a ‘normal’ value.To have a language, we need to provide constructsthat manipulate such domain concepts. This is easyin functional languages: we can simply define higherorder functions called combinators, taking domainconcepts as inputs and combining them into morecomplex ones, just like what procedures do to prim-itive data. For this reason, EDSLs are also knownas combinator libraries—libraries that not just of-fer domain-specific operations, but alsomore impor-tantly combinators that manipulate them. We illus-trate this idea by developing an example EDSL.

A classic example: parser combinatorsOur aim is to develop a parsing EDSL for the follow-ing BNF grammar:

float ::= sign? digit+ (′.′ digit+)?

Like any language, an EDSL has syntax and se-mantics. In this embedded setting, the syntax issimply the interface of the library containing the

query = do cust ← table customersrestrict (cust !city . == . ”London”)project (cust !customerID)

(a) HaskellDB [121] for generating and executing SQL statements

htmlPage content =(header � ((thetitle � ”Mypage”)

+++ (script ! [thetype ”text/javascript”,src ”http : //...”] � ””)

)) +++ (body � content)

(b) (X)HTML [119] for producing XHTML

mouseTurn g u =turn3 xVector3 y (turn3 zVector3 (−x) g)where

(x, y) = vector2XYCoords (π∗mouseMotion u)

mouseSpinningPot u =mouseTurn (withColorG green teapot) u

(c) Fran [120] for composing interactive, multi-media animations.

Figure 1. Code fragments in three EDSLs.

Page 14: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 13

representation of the domain concept, and the oper-ations on it; and the semantics is the implementationof the operations in the host language.

A parser is a program that receives a piece oftext as the input, analyses the structure of the text,and produces an output usually in the form of treesthat can bemore convenientlymanipulated by otherparts of a compiler. A parser can be represented as afunction:

newtype Parser α = MkP (String→[(α, String)])

The type Parser is a new type, distinct but iso-morphic to its underlying type of a function fromstrings to lists of parsing results, depending on howmany ways the parse could succeed, or fail with anempty list. The parameterized type α is the tree pro-duced by parsing, and is paired with the remain-ing unparsed string. In DSL terminology, Parser isthe domain concept we are trying to model andas usual it has an underlying representation as afunction.

Primitive Parsers: With a parser representation athand, we can start building a library to manipulateit. To start with, we define some basic parsers.

item :: Parser Charitem = MkP f

wheref [ ] = [ ]f (c : cs) = [(c , cs)]

The parser item consumes a character of the inputstring and returns it. And a second parser is a parserthat always fails.

zero :: Parser α

zero = MkP f where f = [ ]

These two are the only basic parsers that we will everneed, and all the power of the resulting languagecomes from its combinators.

Parser Combinators: For the grammar we have inmind, our language consists of the following set ofbasic combinators:

sat :: (Char → Bool) → Parser Charplus :: Parser α → Parser α → Parser α

optional :: Parser α → Parser (Maybe α)

In the above, sat enriches item with a predi-cate so that only characters satisfying the predi-cate will be parsed. By providing different predi-cates, it can be specialized to a number of differentparsers:

char x = sat (== x)digit = sat(λx → ′0′ ≤ x ∧ x ≤ ′9′)

For example, digit succeeds with ‘123’ and produces[(‘1’, ‘23’)] as the outcome, but fails (returning [ ])with ‘A23’. Similarly, char only recognizes the char-acter that is passed to it as input and fails on all oth-ers.

Parser plus p q combines the outcomes of apply-ing p and q. In the case when one of the two fails, theoutcome will be the same as using the other one:

sign :: Parser Charsign = (char ′+′) ‘plus‘ (char ′−′)

In the above, the prefix function plus is turned intoan infix one by the surrounding left single quotes.

The combinator optional corresponds to the (?)notation in our grammar allowing an optional fieldto be parsed into Nothing when it is not filled. Notethat here Nothing represents success in parsing, notfailure which is represented by the empty list.

So far, what we have seen are combinators thatare useful for constructing parsers recognizing indi-vidual components of a grammar. A crucial missingpart is a way to sequence the individual components,so that individual parsers are chained together andapplied in sequence. For example, our float grammaris a chain of sign, digits, and fraction parsers. In an-other words, we need a way to structure the parsingcomputation. Sounds familiar? Monads introducedin the previous subsection fit the bill very well.

Just likeMaybe, Parser α is a monad with its ownbind and return:

(�=) :: Parser α → (α → Parser β)→Parser β

return :: α → Parser α

Nowwe are ready to define combinators that repeat-edly apply a parser:

zeroOrMore :: Parser α → Parser [α]zeroOrMore p =

do {x ← p;xs ← zeroOrMore p;return (x : xs)}

‘plus‘ return [ ]

oneOrMore :: Parser α → Parser [α]oneOrMore p =

do x ← pxs ← zeroOrMore preturn (x : xs)

Parser zeroOrMore p returns each application of pas a list. For example, applying (zeroOrMore digit)to ′12a′ results in [(′12′,′ a′), (′1′,′ 2a′), (′′,′ 12a′)].Parser oneOrMore p is similar to zeroOrMore p ex-cept requiring p to apply at least once.

Just to show that the use of monad has not pre-vented us from doing the same kind of equationalreasoning as before, we list a few arbitrarily selected

Page 15: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

14 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

laws as an example:

zero �= p ≡ pzero ‘plus‘ p ≡ pp ‘plus‘ (q ‘plus‘ r) ≡ (p ‘plus‘ q) ‘plus‘ r(p ‘plus‘ q) �= r ≡ (p �= r) ‘plus‘ (q �= r)

Finally, we can directly translate the BNF grammarat the beginning of this subsection to the followingexecutable parser:

float = dosgn ← optional signin ← oneOrMore digitfrac ← optional (do {c har ′.′; oneOrMore digit})return (mkFloat sgn in frac)

We stop here and look at what we have learnt fromthis exercise. Readers interested in knowing moreabout parser combinators may start with HuttonandMeijer’s tutorials [79,80] for more combinatorsand techniques for improving efficiency, and severalmore papers on the subject [81–85].

(i) Combinators are the key. The parser librarywe have developed is a language. It is notso much about what specific operationsare provided, but the unlimited possibilitiesthrough creative programming. As we cansee, the very small number (two in our case)of basic parsers, which is typical in EDSLs,can be combined in different ways to pro-duce highly complex programs. This powercomes from the combinatorswhichhinge onhigher order functions.

(ii) Monads are very useful.Themonadic sequen-tial combination is an excellent formulationof a recurring pattern: a sequence of opera-tions are performed in turn andhave their re-sults combined in the end.Wehave relied onit to program parsers that goes beyond sim-ply consuming a single character.

When the semantics of the domain concepts is ob-vious, directly encoding the operations that can beperformed on them often results in an elegant EDSLimplementation. This is exactly what we did for theparser example: the set of combinators implementswhatwe cando toparsers and the set is easily extensi-ble bydefiningnewcombinators.On theother hand,addingnewdomain concepts usually requires a com-plete reimplementation. Moreover, with this directapproach, performance of the domain-specific pro-grams relies on the optimization of the host languagecompiler, which is hard to predict and control.

An alternative embedding technique is to gener-ate code from the EDSL programs: the domain con-cepts are represented as an abstract syntax tree, and

a separate interpretation function provides the se-mantics of the syntax constructs, resulting in a socalled embedded domain-specific compiler [86]. In thiscase, the host language is used only at ‘compile time’;the EDSL programmer can use the full power of thehost language to express the program, but at run-time, only the generated code needs be executed.This approach is sometimes referred as deep embed-ding in contrast to the above more direct shallowembedding. The separation of phases in deep em-bedding provides opportunities for domain-specificoptimizations as part of the interpretation functionand adding new domain concepts simply means ad-ditional interpretation functions.On the other hand,extending the set of operations involves modify-ing the abstract syntax and existing interpretationfunctions.

The two embedding approaches are dual in thesense that the former is extensible with regard toadding operations while the latter is extensible withregard to adding concepts [87]. The holy grail ofembedded language implementation is to be ableto combine the advantages of the two in a singleimplementation—a manifestation of the expressionproblem [88]. Current research addresses the prob-lem at two levels: exploiting sufficiently expressivehost languages for a modular representation of theabstract syntax tree [89–92], or combining the shal-low and deep embedding techniques [93]. Notablyin [91], the technique also addresses another sourceof inefficiency with embedded languages namely thetagging and untagging required formanipulating theabstract syntax trees represented as datatypes.

Lastly, the connection between EDSLs andmon-ads may extend beyond the implementation level.It has become popular to include the monadic con-structs as part of the EDSL surface language, whichsparks interesting interactions with the underlyingtype system [94–96].

PARALLEL AND DISTRIBUTEDCOMPUTATIONFor a long time, parallel and distributed program-ming was seen as a specialized activity by special ex-perts. This situation is currently changing extremelyrapidly with pervasive parallel and distributed en-vironments such as multicore/manycore hardwareand cloud computing. With the Google’s MapRe-duce [97], one can now easily write a program toprocess and generate large data sets with a parallel,distributed algorithm on a cluster. The MapRe-duce model is actually inspired by the map andreduce functions commonly used in functionalprogramming.

Page 16: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 15

Functional programming languages offer amedium where programmers can express the fea-tures of parallel algorithms, without having to detailthe low-level solutions [98–100]. The high level ofprogramming abstraction of function compositionand higher order functions simplifies the task ofprogramming, fosters code reuse, and facilitatesthe development of substantially architecture-independent programs. The absence of side effectsavoids the unnecessary serialization which is afeature of most conventional programs.

Parallel functional programmingFunctional languages have two key properties thatmake them attractive for parallel programming: theyhave powerful abstraction mechanisms (higher or-der functions and polymorphism) for supporting ex-plicit parallel programming known as skeleton paral-lel programming that abstracts over both computa-tion and coordination and achieves the architecture-independent style of parallelism, and they have noside effect that can eliminate unnecessary depen-dences for easy parallelization.

Skeleton parallel programmingParallel primitives (also called parallel skeletons[101,102]) intend to encourage programmers tobuild a parallel program from ready-made compo-nents forwhich efficient implementations are knownto exist, making the parallelization process easier.

The higher order functions discussed in the sec-tion entitled ‘Functional forms’ can be regarded asparallel primitives suitable for parallel computationover parallel lists, if we impose some properties onthe argument operators. Three known data parallelskeletonsmap, reduce, and scan canbedefined as spe-cial instances of foldr op e .The definition ofmap hasbeen given in the section entitled ‘Functional forms’,and the definitions of reduce and scan are as follows:

reduce op e = foldr op escan op e = map (foldr op e) ◦ inits

where op is an associative operator, and scan is de-fined as a composition ofmap (foldr op e) and inits.Note that reduce is different from foldr in that theoperator op it can accept must be associative, whichrestricts the type of reduce (the operator must com-bine operands of the same type), but allows theimplementation greater freedom to choose an or-der of combination (foldr always combines fromright to left). The definitions above just define thesemantics of reduce and scan, not necessarily theirimplementation.

It has been shown thatmap, reduce, and scan havenicemassively parallel implementations onmany ar-

chitectures [102,103]. If k and an associative ⊕ useO(1) parallel time, thenmap k can be implementedusing O(1) parallel time, and both reduce op e andscan op e canbe implementedusingO(logN)paral-lel time (N denotes the size of the list). For example,reduce op can be computed in parallel on a tree-likestructure with the combining operator op applied inthe nodes, whilemap k is computed in parallel withk applied to each of the leaves.The study on efficientparallel implementation of scan op e can be foundin [102], which plays an important role in the im-plementation of parallel functional language NESL[104].

Just like foldr being the most important higherorder function for manipulating lists sequentially,reduce plays the most important role in parallel pro-cessing of lists. If we can parallelize foldr as a parallelprogram using reduce, we can parallelize any sequen-tial function that is defined in terms of foldr (Thisagain shows an advantage of structuring programsusing general functional forms.). This has attracteda lot of work in developing programming theories toparallelize foldr [105–108]. One known theorem forthis parallelization is the so-called third homomor-phism theorem [109], which shows that foldr op ecan be parallelized as a composition of a map and areduce if and only if there exists op′ such that the fol-lowing holds:

foldr op ′ e = foldr op e ◦ reverse

In other words, this theorem says that a foldr is par-allelizable if and only if can bewritten as a foldr on itsreverse list. With this theorem, we can see that manyof the functionsdefined in the section entitled ‘Func-tional forms’, such as sum, sort, maxlist, and reverse,can be parallelized as a composition of a map and areduce. Importantly, this parallelization is not just aguide toprogrammers but also canbedone automat-ically [110].

Easy parallelizationPurely functional languages have advantages whenit comes to (implicit) parallel evaluation [111,112].Thanks to the absence of side effects, it is always safeto execute computations of subexpressions in paral-lel.Therefore, it is straightforward to identify thepar-allel task in a program,whichwould require complexdependency analysis when parallelizing imperativeprograms.

Parallel Haskell provides two operators pseq andpar for parallelization: pseq e1 e2 evaluates e1 thene2 in a sequential order, and par e1 e2 is a kind offork operation, where e1 is started in parallel withe2 and the result of e2 is returned. Consider the

Page 17: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

16 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

following normal Haskell function that implementsthe well-knownQuicksort algorithm:

sort [ ] = [ ]sort (x : xs ) = less++ [x]++ greater

whereless = sort [y | y ← xs , y < x]greater = sort [y | y←xs , y ≥ x]

The following parallel version is just a littlemore complicated (with addition of the under-lined codes); greater is computed in parallelwith less by wrapping the original expressionless++ [x]++ greaterwith par greater and pseq less.

parSort [ ] = [ ]parSort (x : xs ) =par greater (pseq less

(less++ [x]++ greater))whereless = parSort [y | y ← xs , y < x]greater = parSort [y | y ← xs , y ≥ x]

We can further control the granularity of the paralleltask by switching to the normal sort when the num-ber of elements of list is shorter enough.

parSort [ ] = [ ]parSort l@(x : xs )

| shorter l = sort l| otherwise =

par greater (pseq less(less++ [x]++ greater))

whereless = parSort [y | y ← xs , y < x]greater = parSort [y | y ← xs , y ≥ x]

It is worth noting that parallel functional programsare easy to debug. Regardless of the order in whichcomputations are executed, the result of theprogramwill always be the same. Specifically, the result will beidentical to that obtained when the program is runsequentially. This implies that programs can be de-bugged sequentially, which represents a huge savingin effort.

Distributed functional programmingDistributed systems, by definition, do not sharememory between nodes (computers)—whichmeans that the imperative approach to parallelprogramming, with shared mutable data structures,is inappropriate in a distributed setting. Instead,nodes communicate by copying messages fromsender to receiver; copying a mutable data structurechanges semantics, because mutation of one copyis not reflected in the other, but immutable datacan be copied transparently. This makes functional

qsort([ ]) → [ ];qsort([X|Xs]) →

Parent = self (),Less = [ Y || Y ← Xs, Y < X ],Grtr = [ Y || Y ← Xs, Y >= X ],spawn(fun() → Parent ! {less, qsort(Less)} end),spawn(fun() → Parent ! {grtr , qsort(Grtr)} end),receive {less,SortedLess} →

receive {grtr ,SortedGrtr} →SortedLess ++ [X] ++SortedGrtr

endend.

Figure 2. Parallel QuickSort in Erlang.

programming, with its immutable data structures,a natural fit. For systems which are designed to bescalable, in which overall system performance canbe increased just by adding more nodes, it makessense to use the same share-nothing communicationbetween processes running on the same node, sothat they may easily be deployed across multiplenodes as new nodes are added. Distributed systemscan also offer high reliability, by using redundancyto tolerate failures, and in-service upgrade, byupgrading one node at a time while the otherscontinue to deliver service.

Erlang was designed at Ericsson in the late 1980sfor building systems of this kind, originally for thetelecom domain [113]. Later, Erlang proved to beideal for building scalable internet services, andmany start-ups have used it as their ‘secret sauce’.Thefirst of thesewasBluetail AB, founded in 1998 todevelop among others an SSL accelerator in Erlang,and sold for $140 million less than 18 months later;the most spectacular to date is WhatsApp, whoseback-end servers arebuilt inErlang, and sold toFace-book in 2014 for $22 billion.

Erlang is a simple functional language with aslightly wordier syntax than Haskell; the factorialfunction defined in the introduction would be writ-ten in Erlang as follows:

fac(0) → 1;fac(N) when N > 0 → N ∗ fac(N − 1)

Erlang provides immutable lists and tuples, andLISP-like atoms, but no user-defined datatypes. Er-lang lacks a static type system (Although many de-velopers useDialyzer [114], a static analysis tool thatcan detect many type errors.)—a reasonable choicesince dynamic code loading, necessary for in-serviceupgrades, is difficult to type statically to this day.

To this functional core, Erlang adds featuresfor concurrency and message passing. For example,Fig. 2 presents a (not very efficient) parallel versionof QuickSort in Erlang. This function uses patternmatching on lists to select between the case of anempty list and a cons ([X|Xs] means x : xs), and

Page 18: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 17

in the latter case uses list comprehensions to selectthe elements less than or greater than the pivot, thenspawns two new processes to sort each sublist re-cursively. Spawning a process calls the function pro-vided (as an Erlang λ-expression, fun() → . . . end)in the new process. Each of these processes sendsthe result of its recursive sort back to the parent pro-cess (Parent ! . . .), using the parent’s process identi-fier, which is obtained by calling self (). Each resultis tagged with an atom (less or grtr), which allowsthe parent process to receive the results in the cor-rect order—messages wait in the recipient’s ‘mail-box’ until a matching receive removes them fromit, so it doesn’t matter in which order the messagesfrom the child processes actually arrive. Erlang pro-cesses share no memory—they each have their ownheap—which means that the lists to be sorted mustbe copied into the new process heaps.This is whywefilter Xs to extract the less and greater elements be-fore starting the child processes: it reduces the costsof copying lists.Theadvantage of giving eachprocessits own heap is that processes can garbage collect in-dependently while other processes continue work-ing, which avoids long garbage collection pauses andmakes Erlang suitable for soft real-time applications.

Erlang addsmechanisms for one process tomon-itor another, turning a crash in the monitored pro-cess into a message delivered to themonitoring one.These mechanisms are used to support fault toler-ance, with a hierarchy of supervisor processes whichare responsible for restarting subsystems that fail;indeed, Erlang developers advocate a ‘let it crash’approach, in which error-handling code (which isoften complex and poorly tested) is omitted frommost application code, relying on the supervisors forfault tolerance instead. Common patterns for build-ing fault-tolerant systems are provided in the ‘OpenTelecom Platform’ libraries—essentially higher or-der functions that permit fault-tolerant systems tobe constructed just by instantiating the application-dependent behaviour.

Erlang’s approach to concurrency and distribu-tion has been very successful, and has been widelyemulated in other languages—for example, CloudHaskell [115] provides similar features to Haskelldevelopers. One of the best known ‘clones’ is theAkka library for Scala [15],which is used amongoth-ers to build Twitter’s back-end services.

FUNCTIONAL THINKING IN PRACTICE

Functional programming has had big influences oneducation and other language design, and seen sig-nificant uses in industry.

EducationThe style of teaching functional languages asfirst languages was pioneered by MIT in the1980s, where functional language scheme wastaught in the first course using the famous text-book Structure and Interpretation of ComputerPrograms [116]. Now many universities suchas Oxford (Haskell) and Cambridge (ML) fol-low this functional-first style. In a recent survey(http://www.pl-enthusiast.net/2014/09/02/who-teaches-functional-programming/), 19 out of top30 American universities in the US News 2014Computer Science Ranking give their undergrad-uate students a serious exposure to functionallanguages. Compared to the other programming-first implementations, the functional-first approachhas the advantages of reducing the effect of diversityof students in background, letting students focuson more fundamental issues, think more abstractly,and touch ideas of recursion, data structure, func-tions as first class data earlier. In fact, one of theexplicit goals of Haskell’s designers was to createa language suitable for teaching. Indeed, almost assoon as Haskell was defined, it was being taught toundergraduates at Oxford and Yale.

For learning the latest advanced functional pro-gramming techniques, there has been an excellentseries of International Summer Schools on Ad-vanced Functional Programming since 1995. Fivesuch summer schools have been held so far in 1995,1996, 1998, 2002, and 2004, with all lecture notespublished in Lecture Notes in Computer Science bySpringer. For the new applications of functional pro-gramming, there has been another series of SummerSchools on Applied Functional Programming orga-nized by Utrecht University since 2009. The two-week course covers applications of functional pro-gramming, concentrating on topics such as languageprocessing, building graphical user interfaces, net-working, databases, and programming for the web.

For exchanging ideas of functional programmingin education, there is a series of International Work-shops on Trends in Functional Programming in Ed-ucation since 2012, where novel ideas, classroom-tested ideas, and work in progress on the use offunctional programming in education are discussedamong researchers and teachers. They have previ-ously been held in St Andrews, Scotland (2012);Provo Utah, USA (2013); and Soesterberg, theNetherlands (2014).

Influences on other languagesIdeas originated from functional programmingsuch as higher order functions, list structure, type

Page 19: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

18 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

inference, etc. havemade their way into the design ofmany modern programming languages, unleashinginfluences in an unostentatious manner. It is wellconceivable that ‘main stream’ programmers maybe using functional features in their code withoutrealizing.

One of the early examples of such is blocks inSmalltalk—a way of expressing lambda expressionsand therefore higher order functions.More recently,the development of C# is influenced by functionalprogrammers working in Microsoft. The LINQ fea-tures are directly inspired by monads and functionallists. Lambda expressions are introduced in C# 3.5,but higher order programming had been possibleearlier on through delegates. Type inference is partof C#’s design and generics (polymorphism) areadded in C# 2.0.

Java’s generic type system introduced in Java5 is based on ML’s Hindley–Milner type systems.Subsequent releases gradually introduced type in-ference, another feature that is usually associatedwith functional languages. Java 8 embraced func-tional programming by releasing a wealth of featuresthat specifically aimed at facilitating such a program-ming style. It includes dedicated support for lambdaexpressions and the passing of functions as methodarguments (i.e. higher order functions), which isfurther made easy by the new feature of methodreferences.

C++ aboards the lambda expression train inC++11. A particular merit of this C++ feature, asopposed to lambdas in other imperative languages,is that it offers fine-grained control over variable cap-ture. Programmers are able to declare in their defini-tions whether the lambda bodies may refer to exter-nal variables (variables that are not formally declaredas parameters) by value, by reference, or not at all—astep towards purity.

Modern multiparadigm languages often havegood provision of functional features. Ruby is ad-mitted by its inventor as having Lisp as its originand blocks at its core. Additional lambda syntax isadded in Ruby 1.9. Python adopted the list compre-hensionnotation andhas support for lambda expres-sions. The Python standard library includes manyfunctional tools imported from Haskell and Stan-dardML. Scala is an object-functional language thathas full support for functional programming. In addi-tion to a strong static type system, it also features cur-rying, type inference, immutability, lazy evaluation,and pattern matching.

Meijer’s reactive extensions (‘RX’) [117] enable.NET developers to manipulate asynchronous datastreams as immutable collections with purely func-tional operations defined over them. RX simplifiesthe construction of event-driven reactive programs

dramatically. The design has been copied in manyother languages, perhaps most notably at Netflix,where RxJava is heavily used in the Netflix API.

Uses in industryIt has often proven easier to adopt functionalprogramming in small, new companies, ratherthan in large, existing software developmentorganizations. By now, there have been many,many start-ups using functional programmingfor their software development. One of the firstwas Paul Graham’s Viaweb, which built a webshop system in Lisp, and was later sold to Yahoo.Graham’s well-known article ‘Beating the Averages’(http://www.paulgraham.com/avg.html) discussesLisp’s importance as Viaweb’s ‘secret weapon’.He writes of studying competitors’ job adverts:‘The safest kind were the ones that wanted Oracleexperience. You never had to worry about those.You were also safe if they said they wanted C++or Java developers. ...If I had ever seen a job postinglooking for Lisp hackers, I would have been reallyworried.’

The first company to useHaskell wasGalois, whodevelop ‘high assurance’ software, primarily undergovernment contracts. Galois develop their code inHaskell—which in itself helps to ensure quality—but also use property-based testing, and the theo-rem provers we have discussed in this paper. Morerecently, Facebook boasts its spam detecting andremediating system being the largest Haskell de-ployment currently in existence, actively and auto-matically fighting off vast amounts of undesirablecontent from reaching its users. At the heart of thesystem is aDSL forwriting the detection logic, firstlyimplemented in FXL (an in-house functional lan-guage) and is being migrated to Haskell at themoment.

Erlang, with its roots in industry, has a strongstart-up culture. The first Erlang start-up, BluetailAB, was set up after Ericsson decided to discour-age the use of Erlang internally. Many key membersof the Erlang team left Ericsson to found a com-pany focussing on scalable and highly reliable inter-net products; within 18 months Bluetail was sold toAlteonWeb Systems for $150 million.The founderswere soon starting new companies, including KlarnaAB (providing invoicing services to web shops inseven European countries) and Tail-f (sold to Ciscoin 2014 for $175 million). The highest profile Er-lang start-up to date, though, is WhatsApp, boughtby Facebook in 2014 for $22 billion. A tech blogat the time asked ‘How do you support 450 mil-lion users with only 32 engineers? For WhatsApp,

Page 20: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 19

acquired earlier thisweek byFacebook, the answer isErlang’.This illustrates nicely the benefits of produc-tivity, scalability, and reliability that functional pro-gramming delivers.

Functional programming has also found manyusers in the financial sector, thanks not least toPeyton-Jones et al’s seminal work on modelling fi-nancial contracts in Haskell [118]. Traders need toevaluate all kinds of financial derivatives quickly, sothey can decide at which price to buy or sell them.But new, ingenious derivatives are being inventedconstantly, forcing traders to update their evalua-tion software continuously. By providing combina-tors for modelling contracts, this task can be accel-erated dramatically, bringing a substantial advantageto traders who use them—the first trader able toevaluate a new derivative correctly stands to make aconsiderable profit. Credit Suisse was the first to usethis technology, with the help of Augustsson, whonowplays a similar role at StandardandChartered—but these are far from the only examples. Functionalprogramming is also used for automated trading atJane Street, whose systems are built in OCaml. Theclarity and quality of OCaml code helps Jane Streetensure that there are no bugs, which might rapidlylose large sums of money.

Languages such as Scala and Clojure (which runon the JVM) and F# (which runs on .NET) aimto be less disruptive, by integrating with an existingplatform. They are enjoying wide adoption; for ex-ample, Apache Spark, a popular open-source frame-work for Big Data analytics, is largely built in Scala.Nowadays, there are successful companies whosebusiness idea is to support the adoption of func-tional programming by their customers: Erlang So-lutions (for Erlang), Typesafe (for Scala), Cogni-tect (forClojure),Well-typed andFPComplete (forHaskell).

New applications of functional programmingare appearing constantly. A good way to followthese developments is via developer conferencessuch as the Erlang Factory, Scala Days and Clo-jure/conj, and also via the annual conference onCommercial Applications of Functional Program-ming (http://cufp.org) , held in association withICFP.

CONCLUSIONTwenty-five years ago, functional programming washigh in the sky, favoured only by researchers in theivory tower. Twenty-five years on, it has toucheddown on the ground and had a wide impact on thesociety as a new generation of programming. Wherewill functional programming be twenty-five yearsfrom now?

REFERENCES1. Hughes, J. Why functional programming matters. Comput J1989; 32: 98–107.

2. Hudak, P, Jones, SLP and Boutel, WP et al. Report on the pro-gramming language Haskell a non-strict purely functional lan-guage. SIGPLAN Not 1992; 27: 1.

3. Bird, R. Introduction to Functional Programming, 2nd edn. Up-per Saddle River, New Jersey: Pearson Education, 1998.

4. Hudak, P. The Haskell School of Expression: Learning Func-tional Programming Through Multimedia. New York, NY, USA:Cambridge University Press, 2000.

5. Paulson, LC. ML for the Working Programmer, 2nd edn. NewYork, NY, USA: Cambridge University Press, 1996.

6. Armstrong, J. Programming Erlang: Software for a ConcurrentWorld. Raleigh: Pragmatic Bookshelf, 2007.

7. Milner, R, Tofte, M and Macqueen, D. The Definition of Stan-dard ML. Cambridge, MA, USA: MIT Press, 1997.

8. Minsky, Y,Madhavapeddy, A and Hickey, J. RealWorld OCaml:Functional Programming for theMasses. O’Reilly Media, 2013.

9. Minsky, Y. Ocaml for the masses. Commun ACM 2011; 54: 53–8.

10. HansenMR Rischel, H. Functional Programming Using F#. NewYork, NY, USA: Cambridge University Press, 2013.

11. Steele, GL, Jr. Common LISP: The Language. Newton, MA,USA: Digital Press, 1984.

12. Seibel, P. Practical Common Lisp, 1st edn. Berkely, CA, USA:Apress, 2012.

13. Dybvig, RK. The Scheme Programming Language, 4th edn.Cambridge: The MIT Press, 2009.

14. Felleisen, M, Findler, RB and Flatt, M et al. Krishnamurthi. Howto Design Programs: An Introduction to Programming and Com-puting. Cambridge, MA, USA: MIT Press, 2001.

15. Wampler, D and Payne, A. Programming Scala: Scalabil-ity= Functional Programming+Objects, 1st edn. O’ReillyMe-dia, 2009.

16. Halloway, S. Programming Clojure, 1st edn. Raleigh, NC: Prag-matic Bookshelf, 2009.

17. Claessen, K and Hughes, J. QuickCheck: a lightweight toolfor random testing of Haskell programs. In Proceedings of theFifth ACM SIGPLAN International Conference on FunctionalProgramming, ICFP ’00. New York, NY, USA: ACM, 2000, 268–79.

18. Leroy, X. Formal certification of a compiler back-end or: pro-gramming a compiler with a proof assistant. In 33rd ACM sym-posium on Principles of Programming Languages. New York,NY, USA: ACM Press, 2006, 42–54.

19. Yang, X, Chen, Y and Eide, E et al. Finding and understandingbugs in C compilers. In Proceedings of the 32nd ACM SIGPLANConference on Programming Language Design and Implemen-tation, PLDI ’11. New York, NY, USA: ACM, 2011.

20. Hinze, R. Generics for the masses. J Funct Progr 2006; 16: 451–83.

21. Chetali, B. Security testing and formal methods for high lev-els certification of smart cards. In Proceedings of the 3rd In-ternational Conference on Tests and Proofs, TAP ’09. Berlin:Springer, 2009, 1–5.

Page 21: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

20 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

22. Barthe, G, Gregoire, B and Zanella Beguelin, S. Formal certification of code-based cryptographic proofs. In Proceedings of the 36th Annual ACMSIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL ’09. NewYork, NY, USA: ACM, 2009, 90–101.

23. Hughes, J. QuickCheck testing for fun and profit. In Proceedings of the9th International Conference on Practical Aspects of Declarative Languages,PADL’07. Berlin: Springer, 2007, 1–32.

24. Arts, T, Hughes, J and Johansson, J et al. Testing telecoms software withQuviq QuickCheck. In Proceedings of the 2006 ACM SIGPLAN Workshop onErlang, ERLANG ’06New York, NY, USA: ACM, 2006, 2–10.

25. Hughes JM Bolinder, H. Testing a database for race conditions withQuickCheck: none. In Proceedings of the 10th ACM SIGPLAN Workshop onErlang, Erlang ’11. New York, NY, USA: ACM, 2011, 72–7.

26. Arts, T, Hughes, J and Norell, U et al. Testing autosar software withQuickCheck. In Testing: Academic and Industrial Conference—Practice andResearch Techniques, Part of the ICST Workshop Proceedings. Graz, Austria:IEEE Digital Library, 2015.

27. Gill, A, Launchbury, J and Peyton Jones, SL. A short cut to deforestation.In Proceedings of the Conference on Functional Programming Languagesand Computer Architecture, FPCA ’93. New York, NY, USA: ACM, 1993,223–32.

28. Takano, A and Meijer, E. Shortcut deforestation in calculational form. In Pro-ceedings of the Seventh International Conference on Functional ProgrammingLanguages and Computer Architecture, FPCA ’95. New York, NY, USA: ACM,1995, 306–13.

29. Hu, Z, Iwasaki, H and Takeichi, M et al. Tupling calculation eliminates multipledata traversals. In Proceedings of the Second ACM SIGPLAN InternationalConference on Functional Programming, ICFP ’97. New York, NY, USA: ACM,1997, 164–75.

30. Farmer, A, Gill, A and Komp, E et al. The hermit in the machine: a plugin for theinteractive transformation of GHC core language programs. In Proceedings ofthe 2012 Haskell Symposium, Haskell ’12. New York, NY, USA: ACM, 2012,1–12.

31. Fegaras, L and Sheard, T. Revisiting catamorphisms over datatypes with em-bedded functions. In Proceedings of the 23rd ACM SIGPLAN-SIGACT Sympo-sium on Principles of Programming Languages, POPL ’96. New York, NY, USA:ACM, 1996, 284–94.

32. Meijer, E, Fokkinga, M and Paterson, R. Functional programming with ba-nanas lenses envelopes and barbed wire. In Proceddings of the 5th ACMConference on Functional Programming Languages and Computer Architec-ture (LNCS 523). Cambridge, MA: ACM, 1991, 124–44.

33. Sheard, T and Fegaras, L. A fold for all seasons. In Proceedings of the Con-ference on Functional Programming Languages and Computer Architecture,FPCA ’93. New York, NY, USA: ACM, 1993, 233–42.

34. Hinze, R, Wu, N and Gibbons, J. Conjugate hylomorphisms—or: the motherof all structured recursion schemes. In Proceedings of the 42nd Annual ACMSIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL’15. New York, NY, USA: ACM, 2015, 527–38.

35. Hu, Z, Iwasaki, H and Takeichi, M. Deriving structural hylomorphisms fromrecursive definitions. In Proceedings of the First ACM SIGPLAN InternationalConference on Functional Programming, ICFP ’96. New York, NY, USA: ACM,1996, 73–82.

36. Odersky, M and Wadler, P. Pizza into java: translating theory into practice.In Proceedings of the 24th ACM SIGPLAN-SIGACT Symposium on Princi-ples of Programming Languages, POPL ’97. ACM: New York, NY, USA, 1997,146–59.

37. Wadler, P. Theorems for free! In Proceedings of the Fourth International Con-ference on Functional Programming Languages and Computer Architecture,FPCA ’89. New York, NY, USA: ACM, 1989, 347–59.

38. Reynolds, JC. Types abstraction and parametric polymorphism. In: Mason,R.E.A (ed.). Proceedings of IFIP 9th World Computer Congress. Amsterdam:Elsevier Science Publishers B. V. (North-Holland), 1983, 513–23.

39. Oliveira BCS Moors, A and Odersky, M. Type classes as objects and implicits.In Proceedings of the ACM International Conference on Object Oriented Pro-gramming Systems Languages and Applications, OOPSLA ’10. New York, NY,USA: ACM, 2010, 341–60.

40. Bertot, Y and Casteran, P. Interactive Theorem Proving and Program Devel-opment: Coq’Art The Calculus of Inductive Constructions, 1st edn. SpringerPublishing Company, Incorporated, 2010.

41. Norell, U. Dependently typed programming in Agda. In Proceedings of the6th International Conference on Advanced Functional Programming, AFP’08.Berlin: Springer, 2009, 230–66.

42. Bird, R. Constructive functional programming. In STOP Summer Schoolon Constructive Algorithmics. Ameland, 1989. http://www.staff.science.uu.nl/∼swier101/STOP/.

43. Bird, R and de Moor, O. Algebra of Programming. Upper Saddle River, NJ,USA: Prentice Hall, 1997.

44. Dijkstra, EW. Programming as a discipline of mathematical nature. AmMath-emat Mon Comp J 1974; 81: 608–12.

45. Bird, R. Pearls of Functional Algorithm Design, 1st edn. New York, NY, USA:Cambridge University Press, 2010.

46. Bird RS Moor, O. Solving optimisation problems with catamorphism. In Pro-ceedings of the Second International Conference on Mathematics of ProgramConstruction. London, UK: Springer, 1993, 45–66.

47. Hu, Z, Yokoyama, T and Takeichi, M. Program optimizations and transforma-tions in calculational form. In Summer School on Generative and Transfor-mational Techniques in Software Engineering (LNCS 4043). Braga, Portugal:Springer, 2006, 139–64.

48. Takano, A, Hu, Z and Takeichi, M. Program transformation in calculationalform. ACM Comput Surv 1998; 30.

49. Smith, DR. KIDSa knowledges-based software development system. In:Lowry, MR and McCartney, RD (eds) Proceedings of AAAI’88 Workshop onAutomating Software Design. The MIT Press, 1991, 483–514.

50. deMoor, O and Sittampalam, G. Generic program transformation. InAdvancedFunctional Programming, Lecture Notes in Computer Science. Berlin: Springer,1998, 116–49.

51. Mu, S, Ko, H and Jansson, P. Algebra of programming in Agda: dependenttypes for relational program derivation. J Funct Progr 2009; 19: 545–79.

52. Naiman, L and Hehner, E. Netty: a prover’s assistant. In COMPUTATIONTOOLS 2011: The Second International Conference on Computational Log-ics, Algebras, Programming, Tools, and Benchmarking, Rome, 2011 September25–30.

53. Tesson, J, Hashimoto, H and Hu, Z et al. Program calculation in Coq. In Pro-ceedings of the 13th International Conference on Algebraic Methodology andSoftware Technology, AMAST’10. Berlin: Springer, 2011, 163–79.

54. Katayama, S. Recent improvements of MagicHaskeller. In Proceedings ofWorkshop on Approaches and Applications of Inductive Programming, AAIP’10(LNCS 5812). Berlin: Springer, 2010, 174–93.

55. Katayama, S. An analytical inductive functional programming system thatavoids unintended programs. In Proceedings of the ACMSIGPLAN 2012Work-shop on Partial Evaluation and Program Manipulation, PEPM ’12. New York,NY, USA: ACM, 2012, 43–52.

Page 22: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

REVIEW Hu et al. 21

56. Moggi, E. Computational lambda-calculus and monads. In Proceedings of theFourth Annual Symposium on Logic in Computer Science. Piscataway, NJ,USA: IEEE Press, 1989, 14–23.

57. Moggi, E. Notions of computation and monads. Inf Comput 1991; 93: 55–92.58. Wadler, P. Comprehending monads. In Proceedings of the 1990 ACM Confer-

ence on LISP and Functional Programming, LFP ’90. New York, NY, USA: ACM,1990, 61–78.

59. Wadler, P. The essence of functional programming. In Proceedings of the 19thACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages,POPL ’92. New York, NY, USA: ACM, 1992, 1–14.

60. Peyton Jones SL Wadler, P. Imperative functional programming. In Proceed-ings of the 20th ACM SIGPLAN-SIGACT Symposium on Principles of Program-ming Languages, POPL ’93. ACM: New York, NY, USA, 1993, 71–84.

61. Launchbury, J and Peyton Jones SL, . State in Haskell. Lisp Symb Comput1995; 8: 293–341.

62. Launchbury, J and Sabry, A. Monadic state: axiomatization and type safety. InProceedings of the Second ACM SIGPLAN International Conference on Func-tional Programming, ICFP ’97. New York, NY, USA: ACM, 1997, 227–38.

63. Peyton Jones, S, Gordon, A and Finne, S. Concurrent Haskell. In Proceedingsof the 23rd ACM SIGPLAN-SIGACT Symposium on Principles of ProgrammingLanguages, POPL ’96. New York, NY, USA: ACM, 1996, 295–308.

64. Harris, T, Marlow, S and Peyton-Jones, S et al. Composable memory trans-actions. In Proceedings of the Tenth ACM SIGPLAN Symposium on Principlesand Practice of Parallel Programming, PPoPP ’05. New York, NY, USA: ACM,2005, 48–60.

65. Liang, S, Hudak, P and Jones, M. Monad transformers and modular inter-preters. In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium onPrinciples of Programming Languages, POPL ’95. New York, NY, USA: ACM,1995, 333–43.

66. Steele, GL, Jr. Building interpreters by composing monads. In Proceedingsof the 21st ACM SIGPLAN-SIGACT Symposium on Principles of ProgrammingLanguages, POPL ’94. New York, NY, USA: ACM, 1994, 472–92.

67. Kiselyov, O, Sabry, A and Swords, C. Extensible effects: an alternative tomonad transformers. In Proceedings of the 2013 ACM SIGPLAN Symposiumon Haskell, Haskell ’13. New York, NY, USA: ACM, 2013, 59–70.

68. Schrijvers, T and Oliveira, BCS. Monads zippers and views: virtualizing themonad stack. In Proceedings of the 16th ACM SIGPLAN International Confer-ence on Functional Programming, ICFP ’11. New York, NY, USA: ACM, 2011,32–44.

69. Snyder, M and Alexander, P. Monad factory: type-indexed monads. In Pro-ceedings of the 11th International Conference on Trends in Functional Pro-gramming, TFP’10. Berlin: Springer, 2011, 198–213.

70. Hughes, J. Generalising monads to arrows. Sci Comput Progr 2000; 37: 67–111.

71. Paterson, R. Arrows and computation. In: Gibbons, J and deMoor, O (eds) TheFun of Programming. Palgrave Macmillan, 2003, 201–22.

72. Mcbride, C and Paterson, R. Applicative programming with effects. J FunctProgr 2008; 18: 1–13.

73. Hudak, P, Courtney, A and Nilsson, H et al. Arrows robots and func-tional reactive programming. In Summer School on Advanced FunctionalProgramming 2002, Oxford University (LNCS 2638). Berlin: Springer, 2003,159–87.

74. Devriese, D, Sergey, I and Clarke, D et al. Fixing idioms: a recursion primitivefor applicative DSLs. In Proceedings of the ACM SIGPLAN 2013 Workshop onPartial Evaluation and Program Manipulation, PEPM ’13. New York, NY, USA:ACM, 2013, 97–106.

75. Lindley, S,Wadler, P and Yallop, J. Idioms are oblivious arrows are meticulousmonads are promiscuous. Electron Notes Theor Comput Sci 2011; 229: 97–117.

76. Hudak, P. Building domain-specific embedded languages. ACM Comput Surv.1996; 28, 4es, Article 196.

77. Hudak, P. Modular domain specific languages and tools. In Proceedings of the5th International Conference on Software Reuse, ICSR ’98. Washington, DC,USA: IEEE Computer Society, 1998, 134–42.

78. Hudak, P, Hughes, J and Peyton Jones, S et al. A history of Haskell: being lazywith class. In Proceedings of the Third ACM SIGPLAN Conference on Historyof Programming Languages, HOPL III. New York, NY, USA: ACM, 2007, 12-1-;12-55.

79. Hutton, G and Meijer, E. Monadic parser combinators. Technical ReportNOTTCS-TR-96-4. Department of Computer Science, University of Notting-ham, 1996.

80. Hutton, G and Meijer, E. Monadic parsing in Haskell. J Funct Progr 1998; 8:437–44.

81. Baars, AI, Loh, A and Swierstra, SD. Parsing permutation phrases. J FunctProgr 2004; 14: 635–46.

82. Chakravarty, MMT. Lazy lexing is fast. In Proceedings of the 4th Fuji Interna-tional Symposium on Functional and Logic Programming, FLOPS ’99. London,UK: Springer, 1999, 68–84.

83. Claessen, K. Parallel parsing processes. J Funct Progr 2004; 14: 741–57.84. Ford, B. Packrat parsing: simple powerful lazy linear time functional pearl. In

Proceedings of the Seventh ACM SIGPLAN International Conference on Func-tional Programming, ICFP ’02. New York, NY, USA: ACM, 2002, 36–47.

85. Swierstra SD Duponcheel, L. Deterministic error-correcting combinatorparsers. In Advanced Functional Programming, Second International School-Tutorial Text. London, UK: Springer, 1996, 184–207.

86. Elliott, C, Finne, S and De Moor, O. Compiling embedded languages. J FunctProgr 2003; 13: 455–81.

87. Gibbons, J and Wu, N. Folding domain-specific languages: deep and shallowembeddings (functional pearl). In Proceedings of the 19th ACM SIGPLAN In-ternational Conference on Functional Programming, ICFP ’14. New York, NY,USA: ACM, 2014, 339–47.

88. Wadler, P. The expression problem. Java Genericity Mailing list 1998.http://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt (12November 1998, date last accessed).

89. Axelsson, E. A generic abstract syntax model for embedded languages. In Pro-ceedings of the 17th ACM SIGPLAN International Conference on FunctionalProgramming, ICFP ’12. New York, NY, USA: ACM, 2012, 323–34.

90. Bahr, P and Hvitved, T. Compositional data types. In Proceedings of the Sev-enth ACM SIGPLANWorkshop on Generic Programming, WGP ’11. New York,NY, USA: ACM, 2011, 83–94.

91. Carette, J, Kiselyov, O and Shan, C. Finally tagless partially evaluated: tag-less staged interpreters for simpler typed languages. J Funct Progr 2009; 19:509–43.

92. Swierstra, W. Data types a la carte la carte. J Funct Progr 2008; 18:423–36.

93. Svenningsson, J and Axelsson, E. Combining deep and shallow embeddingfor EDSL. In: Loidl, H-W and Pena, R (eds) Trends in Functional Programming(LCNS 7829). Berlin: Springer, 2013, 21–36.

94. Persson, A, Axelsson, E and Svenningsson, J. Generic monadic constructsfor embedded languages. In: Gill, A and Hage, J (eds) Implementation andApplication of Functional Languages (LCNS 7257). Berlin: Springer, 2012,85–99.

Page 23: How functional programming mattered - Rice …javaplt/411/19-spring/Readings/...How functional programming mattered Article · July 2015 DOI: 10.1093/nsr/nwv042 CITATIONS 5 READS 44

22 Natl Sci Rev, 2015, Vol. 00, No. 0 REVIEW

95. Sculthorpe, N, Bracker, J and Giorgidze, G et al. The constrained-monad prob-lem. In Proceedings of the 18th ACM SIGPLAN International Conference onFunctional Programming, ICFP ’13. New York, NY, USA: ACM, 2013, 287–98.

96. Svenningsson, JD and Svensson, BJ. Simple and compositional reification ofmonadic embedded languages. In Proceedings of the 18th ACM SIGPLAN In-ternational Conference on Functional Programming, ICFP ’13. New York, NY,USA: ACM, 2013, 299–304.

97. Dean, J and Ghemawat, S. Mapreduce: simplified data processing on largeclusters. In Proceedings of the 6th Conference on Symposium on OperatingSystems Design and Implementation, OSDI’04. Berkeley, CA, USA: USENIXAssociation, 2004, 10.

98. Backus, J. Can programming be liberated from the von neumann style?: a func-tional style and its algebra of programs. Commun ACM 1978; 21: 613–41.

99. Jones, SP. Parallel implementations of functional programming languages.Comput J 1989; 32: 175–86.

100. Loidl HW Rubio, F and Scaife, N et al. Comparing parallel functional lan-guages: programming and performance. Higher Order Symb Comput 2003; 16:203–51.

101. Cole, M. Higher-order functions for parallel evaluation. In: Hall, CV, Hughes,RJM and O’Donnell, JT (eds). Proceedings of Computing Science DepartmentResearch Report 89/R4. Isle of Bute, Scotland: Glasgow University, 1989,8–20.

102. Cole, M. Algorithmic skeletons : a structured approach to the management ofparallel computation. Research Monographs in Parallel and Distributed Com-puting, Pitman, London, 1989.

103. Skillicorn DB, . Architecture-independent parallel computation. IEEE Comput1990; 23: 38–51.

104. Blelloch, GE. NESL: a nested data parallel language. Technical Report CMU-CS-92-103. School of Computer Science, Carnegie-Mellon University, 1992.

105. Chin,Wn, Takano, A and Hu, Z. Parallelization via context preservation. In IEEEComputer Society International Conference on Computer Languages. Chicago,USA: Loyola University Chicago, 1998.

106. Hu, Z, Takeichi, M and Chin, W-N. Parallelization in calculational forms. In25th ACM Symposium on Principles of Programming Languages (POPL’98).San Diego, CA, USA: ACM Press, 1998, 316–28.

107. Hu, Z, Takeichi, M and Iwasaki, H. Diffusion: calculating efficient parallel pro-grams. In 1999 ACMSIGPLANWorkshop on Partial Evaluation and Semantics-Based ProgramManipulation (BRICS Notes Series NS-99-1). San Antonio, TX,1999, 85–94.

108. Matsuzaki, K, Hu, Z and Takeichi, M. Towards automatic parallelization oftree reductions in dynamic programming. In 18th ACM Symposium on Par-allelism in Algorithms and Architectures (SPAA 2006). Cambridge, MA, USA:ACM Press, 2006, 39–48.

109. Gibbons, J. The third homomorphism theorem. J Funct Progr 1996; 6: 657–65.110. Morita, K, Morihata, A and Matsuzaki, K et al. Automatic inversion gener-

ates divide-and-conquer parallel programs. In Proceedings of the 2007 ACMSIGPLAN Conference on Programming Language Design and Implementation,PLDI ’07. New York, NY, USA: ACM, 2007, 146–55.

111. Chakravarty MMT Leshchinskiy, R and Jones, SP et al. Data parallel Haskell:a status report. In Proceedings of the 2007 Workshop on Declarative As-pects of Multicore Programming, DAMP ’07. New York, NY, USA: ACM, 2007,10–8.

112. Hammond, K. Why parallel functional programming matters: panel state-ment. In Proceedings of the 16th Ada-Europe International Conferenceon Reliable Software Technologies, Ada-Europe’11 Berlin: Springer, 2011,201–5.

113. Armstrong, J. A history of Erlang. In Proceedings of the Third ACM SIGPLANConference on History of Programming Languages, HOPL III. New York, NY,USA: ACM, 2007, 6–1–6–26.

114. Sagonas, K. Detecting defects in Erlang programs using static analysis. InProceedings of the 9th ACM SIGPLAN International Conference on Principlesand Practice of Declarative Programming, PPDP ’07. NewYork, NY, USA: ACM,2007, 37.

115. Epstein, J, Black, AP and Peyton-Jones, S. Towards Haskell in the cloud. InProceedings of the 4th ACM Symposium on Haskell, Haskell ’11. New York,NY, USA: ACM, 2011, 118–29.

116. Abelson, H, Sussman, GJ and Sussman, J. Structure and Interpre-tation of Computer Programs. Cambridge, MA, USA: MIT Press,1985.

117. Meijer, E. Reactive extensions (rx): curing your asynchronous programmingblues. In ACM SIGPLAN Commercial Users of Functional Programming, CUFP’10. New York, NY, USA: ACM, 2010, 11: 1.

118. Peyton Jones, S, Eber, J-M and Seward, J. Composing contracts: an adventurein financial engineering (functional pearl). In Proceedings of the Fifth ACMSIGPLAN International Conference on Functional Programming, ICFP ’00. NewYork, NY, USA: ACM, 2000, 280–92.

119. Bringert, B. xhtml: an XHTML combinator library. https://hackage.haskell.org/package/xhtml (9 May 2012, date last accessed).

120. Elliott, C and Hudak, P. Functional reactive animation. In Proceedings of theSecond ACM SIGPLAN International Conference on Functional Programming,ICFP ’97. New York, NY, USA: ACM, 1997, 263–73.

121. Leijen, D, Andersson, C and Andersson, M et al. haskelldb: a library of combi-nators for generating and executing SQL statements. https://hackage.haskell.org/package/haskelldb (29 September 2014, date last accessed).

122. Blelloch, GE. Scans as primitive operations. IEEE Trans Comp 1989; 38: 1526–38.

View publication statsView publication stats