際際滷

際際滷Share a Scribd company logo
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

More Related Content

Combinators, DSLs, HTML and F#

  • 1. Combinators, DSLs, HTML and F#Robert Pickering, ALTI
  • 2. About the Presenter2Using F# for about 6 years
  • 3. Oldest F# user outside of Microsoft
  • 4. Written a book about F# (now in its second edition)Spend at least 2 years as a professional functional programmer
  • 5. I have 3 catsContact me:robert@strangelights.comhttp://strangelights.com/blog
  • 6. 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
  • 7. 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
  • 8. 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
  • 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 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
  • 13. 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.
  • 15. Uniform look and feel across many DSLs
  • 16. 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
  • 17. 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
  • 18. The Anatomy of a DSLletexpr = (1N + 2N) * (5N - 2N)valexpr : Expression = Multiply (Add (Constant 1,Constant 2), Subtract (Constant 5,Constant 2))
  • 19. The Anatomy of a DSLExpressions now have an abstract tree like representation:Multiply
  • 20. Add
  • 26. This can then be evaluated
  • 27. 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
  • 29. 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
  • 31. 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>
  • 32. 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
  • 33. Why a DSL for HTML?Tag: html
  • 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 librarySource: Composing contracts: an adventure in financial engineeringPeyton Jones, Eber, Sewardhttp://research.microsoft.com/~simonpj/Papers/financial-contracts/contracts-icfp.htm
  • 43. DSLs for Working with 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 it Work?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 in F#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 FormsText Input 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 Compositional Forms [<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 Compositional FormsConfiguration 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
  • 51. Flowlets Composing FormletsFlowlet.Flowlet.Do {let! info = ContactForms.BasicInfoForm() |> Flowlet.OfFormlet conf1let! contact = ContactForms.ContactInfoForm() |> Flowlet.OfFormlet conf2return info, contact }
  • 52. Flowlets Composing FormletsFlowlet.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 UpCombinator libraries/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# InfoMSDN Center: http://msdn.microsoft.com/fsharp/Users 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. Books