combinators, dsls, html and f#

35
Combinators, DSLs, HTML and F# Robert Pickering, ALTI

Upload: robert-pickering

Post on 12-May-2015

4.574 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Combinators, DSLs, HTML and F#

Combinators, DSLs, HTML and F#

Robert Pickering, ALTI

Page 2: Combinators, DSLs, HTML and F#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

The Anatomy of a DSL

Page 17: Combinators, DSLs, HTML and F#

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#

The Anatomy of a DSL

Page 19: Combinators, DSLs, HTML and F#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

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#

Plotting Graphs Client SideDemo

Page 31: Combinators, DSLs, HTML and F#

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#

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#

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#

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#

Books