KEMBAR78
Combinators, DSLs, HTML and F# | PPTX
Combinators, DSLs, HTML and F#Robert Pickering, ALTI
About the Presenter2Using F# for about 6 years
Oldest F# user outside of Microsoft
Written a book about F# (now in its second edition)Spend at least 2 years as a professional functional programmer
I have 3 catsContact me:robert@strangelights.comhttp://strangelights.com/blog
What is a Combinator?A combinator is a higher-order function that uses only function application and earlier defined combinators to define a result from its arguments.Source: Wikipedia, http://en.wikipedia.org/wiki/Combinatory_Logic
Combinatory Logic in ComputingIn computer science, combinatory logic is used as a simplified model of computation, used in computability theory and proof theory. Despite its simplicity, combinatory logic captures many essential features of computation.Source: Wikipedia, http://en.wikipedia.org/wiki/Combinatory_Logic
Combinator Library"A combinator library offers functions (the combinators) that combine functions together to make bigger functions"[1]. These kinds of libraries are particularly useful for allowing domain-specific programming languages to be easily embedded into a general purpose language by defining a few primitive functions for the given domain.Souce: Wikipedia http://en.wikipedia.org/wiki/Combinator_library[1] “A History of Haskell” Hudak, Hughes, Peyton Jones, Wadler
History of Haskell: Combinator LibrariesWhat is a combinatorlibrary? The reader will search in vain for a definition of this heavily used term, but the key idea is this: a combinator library offers functions (the combinators) that combine functions together to make bigger functions.
History of Haskell: Combinator LibrariesWhat is a combinatorlibrary?The reader will search in vain for a definition of this heavily used term, but the key idea is this: a combinator library offers functions (the combinators) that combine functions together to make bigger functions.
History of Haskell: Combinator LibrariesAnother productive way to think of a combinator library is as a domain-specific language (DSL) for describing values of a particular type.
What is a Domain Specific Language?A programming language tailored for a particular application domain, which captures precisely the semantics of the application domain -- no more, no less.A DSL allows one to develop software for a particular application domain quickly, and effectively, yielding programs that are easy to understand, reason about, and maintain.Hudak
Combinatorsvs DSLsCombinartor libraries are a special case of DSLsSometimes called DSELs (Domain Specific Embed languages)DSELs have several advantages:Inherit non-domain-specific parts of the design.
Inherit compilers and tools.
Uniform “look and feel” across many DSLs
DSLs integrated with full programming language, and with each other.DSELs one disadvantage:Constrained by host language syntax and type systemWhat Makes F# a Suitable for DSLs ?Algebraic data types type Option<'a> = Some x | NoneLambda functionsfun x -> x + 1Define and redefine operatorslet (++) x = x + 1Define custom numeric literalslet x : Expression = 1.0N
The Anatomy of a DSLSyntax Treetype Expression =    | Add of Expression * Expression    | Subtract of Expression * Expression    | Multiply of Expression * Expression    | Constant ofint    | Parameter of stringwithstaticmember (+) (x, y) = Add(x, y)staticmember (-) (x, y) = Subtract(x, y)staticmember (*) (x, y) = Multiply(x, y)moduleNumericLiteralN = letFromZero() = Constant 0letFromOne() = Constant 1let FromInt32 = Constantletparam = ParameterCombinators
The Anatomy of a DSLletexpr = (1N + 2N) * (5N - 2N)valexpr : Expression =  Multiply (Add (Constant 1,Constant 2),           Subtract (Constant 5,Constant 2))
The Anatomy of a DSLExpressions now have an abstract tree like representation:Multiply
Add
Constant 1
Constant 2
Subtract
Constant 5
Constant 2
This can then be evaluated
Or we can preform more advanced analysis The Anatomy of a DSLletevaluateExpression parameters =letrecinnerEval tree =match tree with        | Multiply (x, y) ->innerEval x * innerEval y        | Add (x, y) ->innerEval x + innerEval y        | Subtract (x, y) ->innerEval x - innerEval y        | Constant value -> value        | Parameter key ->Map.find key parametersinnerEvallet expr = (1N + 2N) * (5N - 2N)evaluateExpressionMap.emptyexpr
The Anatomy of a DSL
The Anatomy of a DSLletrecsimplifyExpressionexp =let simpIfPoss op exp1 exp2 =letexp' = op (simplifyExpression exp1, simplifyExpressionexp2)ifexp' = expthenexp' elsesimplifyExpressionexp'matchexpwith    | Multiply(Constant 0, Constant _) -> Constant 0    | Multiply(Constant _, Constant 0) -> Constant 0    | Multiply(Constant n1, Constant n2) -> Constant (n1 * n2)    | Add(Constant n1, Constant n2) -> Constant (n1 + n2)    | Subtract(Constant n1, Constant n2) -> Constant (n1 - n2)    | Multiply(exp1, exp2) ->simpIfPoss Multiply exp1 exp2    | Add(exp1, exp2) ->simpIfPoss Add exp1 exp2    | Subtract(exp1, exp2) ->simpIfPoss Add exp1 exp2    | Constant _ | Parameter _ ->exp
The Anatomy of a DSL
Why a DSL for HTML?<htmlxmlns="http://www.w3.org/1999/xhtml"><head><title></title></head><body><h1>Hello world!</h1><formid="form1"><inputtype="text"name="name"/>    </form></body></html>
Why a DSL for HTML ?HTML has a tree like structureWe need be able to generate and manipulate this tree in an abstract, type safe way
Why a DSL for HTML?Tag: html
Tag: head
Tag: title

Combinators, DSLs, HTML and F#

  • 1.
    Combinators, DSLs, HTMLand F#Robert Pickering, ALTI
  • 2.
    About the Presenter2UsingF# for about 6 years
  • 3.
    Oldest F# useroutside of Microsoft
  • 4.
    Written a bookabout F# (now in its second edition)Spend at least 2 years as a professional functional programmer
  • 5.
    I have 3catsContact me:robert@strangelights.comhttp://strangelights.com/blog
  • 6.
    What is aCombinator?A combinator is a higher-order function that uses only function application and earlier defined combinators to define a result from its arguments.Source: Wikipedia, http://en.wikipedia.org/wiki/Combinatory_Logic
  • 7.
    Combinatory Logic inComputingIn computer science, combinatory logic is used as a simplified model of computation, used in computability theory and proof theory. Despite its simplicity, combinatory logic captures many essential features of computation.Source: Wikipedia, http://en.wikipedia.org/wiki/Combinatory_Logic
  • 8.
    Combinator Library"A combinatorlibrary offers functions (the combinators) that combine functions together to make bigger functions"[1]. These kinds of libraries are particularly useful for allowing domain-specific programming languages to be easily embedded into a general purpose language by defining a few primitive functions for the given domain.Souce: Wikipedia http://en.wikipedia.org/wiki/Combinator_library[1] “A History of Haskell” Hudak, Hughes, Peyton Jones, Wadler
  • 9.
    History of Haskell:Combinator LibrariesWhat is a combinatorlibrary? The reader will search in vain for a definition of this heavily used term, but the key idea is this: a combinator library offers functions (the combinators) that combine functions together to make bigger functions.
  • 10.
    History of Haskell:Combinator LibrariesWhat is a combinatorlibrary?The reader will search in vain for a definition of this heavily used term, but the key idea is this: a combinator library offers functions (the combinators) that combine functions together to make bigger functions.
  • 11.
    History of Haskell:Combinator LibrariesAnother productive way to think of a combinator library is as a domain-specific language (DSL) for describing values of a particular type.
  • 12.
    What is aDomain Specific Language?A programming language tailored for a particular application domain, which captures precisely the semantics of the application domain -- no more, no less.A DSL allows one to develop software for a particular application domain quickly, and effectively, yielding programs that are easy to understand, reason about, and maintain.Hudak
  • 13.
    Combinatorsvs DSLsCombinartor librariesare a special case of DSLsSometimes called DSELs (Domain Specific Embed languages)DSELs have several advantages:Inherit non-domain-specific parts of the design.
  • 14.
  • 15.
    Uniform “look andfeel” across many DSLs
  • 16.
    DSLs integrated withfull programming language, and with each other.DSELs one disadvantage:Constrained by host language syntax and type systemWhat Makes F# a Suitable for DSLs ?Algebraic data types type Option<'a> = Some x | NoneLambda functionsfun x -> x + 1Define and redefine operatorslet (++) x = x + 1Define custom numeric literalslet x : Expression = 1.0N
  • 17.
    The Anatomy ofa DSLSyntax Treetype Expression = | Add of Expression * Expression | Subtract of Expression * Expression | Multiply of Expression * Expression | Constant ofint | Parameter of stringwithstaticmember (+) (x, y) = Add(x, y)staticmember (-) (x, y) = Subtract(x, y)staticmember (*) (x, y) = Multiply(x, y)moduleNumericLiteralN = letFromZero() = Constant 0letFromOne() = Constant 1let FromInt32 = Constantletparam = ParameterCombinators
  • 18.
    The Anatomy ofa DSLletexpr = (1N + 2N) * (5N - 2N)valexpr : Expression = Multiply (Add (Constant 1,Constant 2), Subtract (Constant 5,Constant 2))
  • 19.
    The Anatomy ofa DSLExpressions now have an abstract tree like representation:Multiply
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
    This can thenbe evaluated
  • 27.
    Or we canpreform more advanced analysis The Anatomy of a DSLletevaluateExpression parameters =letrecinnerEval tree =match tree with | Multiply (x, y) ->innerEval x * innerEval y | Add (x, y) ->innerEval x + innerEval y | Subtract (x, y) ->innerEval x - innerEval y | Constant value -> value | Parameter key ->Map.find key parametersinnerEvallet expr = (1N + 2N) * (5N - 2N)evaluateExpressionMap.emptyexpr
  • 28.
  • 29.
    The Anatomy ofa DSLletrecsimplifyExpressionexp =let simpIfPoss op exp1 exp2 =letexp' = op (simplifyExpression exp1, simplifyExpressionexp2)ifexp' = expthenexp' elsesimplifyExpressionexp'matchexpwith | Multiply(Constant 0, Constant _) -> Constant 0 | Multiply(Constant _, Constant 0) -> Constant 0 | Multiply(Constant n1, Constant n2) -> Constant (n1 * n2) | Add(Constant n1, Constant n2) -> Constant (n1 + n2) | Subtract(Constant n1, Constant n2) -> Constant (n1 - n2) | Multiply(exp1, exp2) ->simpIfPoss Multiply exp1 exp2 | Add(exp1, exp2) ->simpIfPoss Add exp1 exp2 | Subtract(exp1, exp2) ->simpIfPoss Add exp1 exp2 | Constant _ | Parameter _ ->exp
  • 30.
  • 31.
    Why a DSLfor HTML?<htmlxmlns="http://www.w3.org/1999/xhtml"><head><title></title></head><body><h1>Hello world!</h1><formid="form1"><inputtype="text"name="name"/> </form></body></html>
  • 32.
    Why a DSLfor HTML ?HTML has a tree like structureWe need be able to generate and manipulate this tree in an abstract, type safe way
  • 33.
    Why a DSLfor HTML?Tag: html
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
    Attribute: name ::nameWhy a DSL for HTML?At this point any red blooded functional programmer should start foaming at the mouth, yelling “build a combinator library”Source: “Composing contracts: an adventure in financial engineering”Peyton Jones, Eber, Sewardhttp://research.microsoft.com/~simonpj/Papers/financial-contracts/contracts-icfp.htm
  • 43.
    DSLs for Workingwith HTML#light – DSL for working with HTML, by SadekDrobi: http://sharplight.codeplex.com/F# Web Tools – Tool kit for Ajax programing, by TomášPetříček: http://www.codeplex.com/fswebtoolsWebSharper – DSL for HTML with F# to JavaScript translator, by IntelliFactory: http://www.intellifactory.com/products/wsp
  • 44.
    Hello worldParagraph Element [<JavaScript>]let Main () =let welcome = P [Text "Welcome"]Div [ welcome Input [Type "Button"; Value "Click me!"] |> On Events.Click (fun e ->welcome.Text <- "Hello, world!") ]Input Button ElementClient Side Event Handler
  • 45.
    How Does itWork?At compile time an extra step takes place:Functions & types are translated into JavaScriptCompiler attempts to optimize JavaScript codeCompiler tries to preserve binding namesF# functions are compiled using the F# quotations system
  • 46.
    Aside: Quotations inF#openMicrosoft.FSharp.Quotations.PatternsopenMicrosoft.FSharp.Quotations.DerivedPatternslet quotation = <@ 1 + 1 @>// a function to interpret very simple quotationsletrecinterpretQuotationexp =matchexpwith | Value (x, typ) whentyp = typeof<int> ->printfn"%d" (x :?> int) | SpecificCall <@ (+) @> (_, _, [l;r]) ->interpretQuotation l printfn"+"interpretQuotation r | _ ->printfn"not supported"// test the functioninterpretQuotation quotation
  • 47.
    Formlets– Compositional FormsTextInput Element[<JavaScript>]let input label err =Controls.Input"" |> Validator.IsNotEmpty err |> Controls.Enhance.WithLabel label [<JavaScript>]letinputInt label err = Controls.Input"" |> Validator.IsInt err |> Controls.Enhance.WithLabellabelAdd Validation ElementAdd Label Element
  • 48.
    Formlets – CompositionalForms [<JavaScriptType>]typeBasicInfo = { Name : string; Age : int } [<JavaScript>]letBasicInfoForm () : Formlet<BasicInfo> =Formlet.Yield (fun name age -> { Name = name; Age = age |> int }) <*> input "Name""Please enter your name" <*> inputInt"Age""Please enter a valid age"Construct form resultConstruct and compose input elements
  • 49.
    Formlets – CompositionalFormsConfiguration optionsletconf = { Render.FormConfiguration.Defaultwith Header = "Sign up" }Render.FormThenResponseconf (ContactForms.BasicInfoForm()) (fun info ->Div [ P [ "Thanks " + info.Name ] P [ "You are " + string info.Age + " years old" ] ])Form and configFunction that constructs result
  • 50.
  • 51.
    Flowlets – ComposingFormletsFlowlet.Flowlet.Do {let! info = ContactForms.BasicInfoForm() |> Flowlet.OfFormlet conf1let! contact = ContactForms.ContactInfoForm() |> Flowlet.OfFormlet conf2return info, contact }
  • 52.
    Flowlets – ComposingFormletsFlowlet.Run (fun (info, contact) -> letresult =matchcontact with | ContactForms.ContactVia.Address address ->"the address: " + address.Street + ", " +address.City + ", " + address.Country| ContactForms.ContactVia.Phone phone ->"the phone number: " + phoneletresults =FieldSet [Legend [Text "Sign-up summary"]P ["Hi " + info.Name + "!" |> Text]P ["You are " + string info.Age + " years old" |> Text]P ["Your preferred contact method is via " + result |> Text]] steps -< [ results ] |> ignore)
  • 53.
    Wrapping It UpCombinatorlibraries/DSL are an excellent way of tackling many problemsEspecially if that problem involves some kind of tree manipulationF# provides the features you need to implement combinator libraries
  • 54.
    Further F# InfoMSDNCenter: http://msdn.microsoft.com/fsharp/User’s forums:http://cs.hubfs.net/forumshttp://stackoverflow.com/tags/F%23Blogs (there are lots of others) : http://blogs.msnd.com/dsymehttp://strangelights.com/blogWebsites :http://code.msdn.microsoft.com/fsharpsampleshttp://code.google.com/hosting/search?q=label:fsharphttp://codeplex.com/Project/ProjectDirectory.aspx?TagName=F%23
  • 55.