combinators, dsls, html and f#
TRANSCRIPT
![Page 1: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/1.jpg)
Combinators, DSLs, HTML and F#
Robert Pickering, ALTI
![Page 2: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/2.jpg)
2
About the Presenter
Contact me:[email protected]://strangelights.com/blog
• Using 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 cats
![Page 3: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/3.jpg)
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
![Page 4: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/4.jpg)
Combinatory Logic in Computing
In 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
![Page 5: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/5.jpg)
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
![Page 6: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/6.jpg)
History of Haskell: Combinator Libraries
What is a combinator library? 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.
![Page 7: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/7.jpg)
History of Haskell: Combinator Libraries
What is a combinator library? 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.
![Page 8: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/8.jpg)
History of Haskell: Combinator Libraries
Another productive way to think of a combinator library is as a domain-specific language (DSL) for describing values of a
particular type.
![Page 9: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/9.jpg)
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
![Page 10: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/10.jpg)
Combinators vs DSLs
• Combinartor libraries are a special case of DSLs– Sometimes 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 system
![Page 11: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/11.jpg)
What Makes F# a Suitable for DSLs ?
• Algebraic data types – type Option<'a> = Some x | None
• Lambda functions– fun x -> x + 1
• Define and redefine operators– let (++) x = x + 1
• Define custom numeric literals– let x : Expression = 1.0N
![Page 12: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/12.jpg)
The Anatomy of a DSLtype Expression = | Add of Expression * Expression | Subtract of Expression * Expression | Multiply of Expression * Expression | Constant of int | Parameter of string with static member (+) (x, y) = Add(x, y) static member (-) (x, y) = Subtract(x, y) static member (*) (x, y) = Multiply(x, y)
module NumericLiteralN = let FromZero() = Constant 0 let FromOne() = Constant 1 let FromInt32 = Constant
let param = Parameter
Syntax Tree
Combinators
![Page 13: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/13.jpg)
The Anatomy of a DSL
let expr = (1N + 2N) * (5N - 2N)
val expr : Expression = Multiply (Add (Constant 1,Constant 2), Subtract (Constant 5,Constant 2))
![Page 14: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/14.jpg)
The Anatomy of a DSL
• Expressions 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
![Page 15: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/15.jpg)
The Anatomy of a DSLlet evaluateExpression parameters = let rec innerEval 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 parameters innerEval
let expr = (1N + 2N) * (5N - 2N)
evaluateExpression Map.empty expr
![Page 16: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/16.jpg)
The Anatomy of a DSL
![Page 17: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/17.jpg)
The Anatomy of a DSLlet rec simplifyExpression exp = let simpIfPoss op exp1 exp2 = let exp' = op (simplifyExpression exp1, simplifyExpression exp2) if exp' = exp then exp' else simplifyExpression exp' match exp with | 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
![Page 18: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/18.jpg)
The Anatomy of a DSL
![Page 19: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/19.jpg)
Why a DSL for HTML?
<html xmlns="http://www.w3.org/1999/xhtml"><head> <title></title></head><body> <h1>Hello world!</h1> <form id="form1"> <input type="text" name="name" /> </form></body></html>
![Page 20: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/20.jpg)
Why a DSL for HTML ?
• HTML has a tree like structure
• We need be able to generate and manipulate this tree in an abstract, type safe way
![Page 21: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/21.jpg)
Why a DSL for HTML?
― Tag: html― Tag: head
― Tag: title― Tag: body
― Tag: h1― Text: Hello world!
― Tag: form― Tag: input
― Attribute: type :: text― Attribute: name :: name
![Page 22: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/22.jpg)
Why 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
![Page 23: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/23.jpg)
DSLs for Working with HTML
• #light – DSL for working with HTML, by Sadek Drobi: http://sharplight.codeplex.com/
• F# Web Tools – Tool kit for Ajax programing, by Tomáš Petříček: http://www.codeplex.com/fswebtools
• WebSharper – DSL for HTML with F# to JavaScript translator, by IntelliFactory: http://www.intellifactory.com/products/wsp
![Page 24: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/24.jpg)
Hello world
[<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!") ]
Paragraph Element
Input Button Element
Client Side Event Handler
![Page 25: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/25.jpg)
How Does it Work?
• At compile time an extra step takes place:– Functions & types are translated into JavaScript– Compiler attempts to optimize JavaScript code– Compiler tries to preserve binding names
• F# functions are compiled using the F# quotations system
![Page 26: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/26.jpg)
Aside: Quotations in F#open Microsoft.FSharp.Quotations.Patternsopen Microsoft.FSharp.Quotations.DerivedPatterns
let quotation = <@ 1 + 1 @>
// a function to interpret very simple quotationslet rec interpretQuotation exp = match exp with | Value (x, typ) when typ = typeof<int> -> printfn "%d" (x :?> int) | SpecificCall <@ (+) @> (_, _, [l;r]) -> interpretQuotation l printfn "+" interpretQuotation r | _ -> printfn "not supported" // test the functioninterpretQuotation quotation
![Page 27: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/27.jpg)
Formlets – Compositional Forms
[<JavaScript>] let input label err = Controls.Input "" |> Validator.IsNotEmpty err |> Controls.Enhance.WithLabel label
[<JavaScript>] let inputInt label err = Controls.Input "" |> Validator.IsInt err |> Controls.Enhance.WithLabel label
Text Input Element
Add Validation Element
Add Label Element
![Page 28: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/28.jpg)
Formlets – Compositional Forms
[<JavaScriptType>] type BasicInfo = { Name : string; Age : int }
[<JavaScript>] let BasicInfoForm () : 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 result
Construct and compose input
elements
![Page 29: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/29.jpg)
Formlets – Compositional Forms
let conf = { Render.FormConfiguration.Default with Header = "Sign up" } Render.FormThenResponse conf (ContactForms.BasicInfoForm()) (fun info -> Div [ P [ "Thanks " + info.Name ] P [ "You are " + string info.Age + " years old" ] ])
Configuration options
Function that constructs result
Form and config
![Page 30: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/30.jpg)
Plotting Graphs Client SideDemo
![Page 31: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/31.jpg)
Flowlets – Composing Formlets
Flowlet.Flowlet.Do { let! info = ContactForms.BasicInfoForm() |> Flowlet.OfFormlet conf1 let! contact = ContactForms.ContactInfoForm() |> Flowlet.OfFormlet conf2 return info, contact }
![Page 32: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/32.jpg)
Flowlets – Composing FormletsFlowlet.Run (fun (info, contact) -> let result = match contact with | ContactForms.ContactVia.Address address -> "the address: " + address.Street + ", " + address.City + ", " + address.Country | ContactForms.ContactVia.Phone phone -> "the phone number: " + phone let results = 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)
![Page 33: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/33.jpg)
Wrapping It Up
• Combinator libraries/DSL are an excellent way of tackling many problems– Especially if that problem involves some kind of
tree manipulation
• F# provides the features you need to implement combinator libraries
![Page 34: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/34.jpg)
MSDN Center: http://msdn.microsoft.com/fsharp/
User’s forums:http://cs.hubfs.net/forumshttp://stackoverflow.com/tags/F%23
Blogs (there are lots of others) : http://blogs.msnd.com/dsymehttp://strangelights.com/blog
Websites :http://code.msdn.microsoft.com/fsharpsampleshttp://code.google.com/hosting/search?q=label:fsharphttp://codeplex.com/Project/ProjectDirectory.aspx?TagName=F%23
Further F# Info
![Page 35: Combinators, DSLs, HTML and F#](https://reader036.vdocuments.mx/reader036/viewer/2022081507/5550f349b4c905417d8b5549/html5/thumbnails/35.jpg)
Books