The document discusses combinator libraries and domain-specific languages (DSLs) in F#. It explains that combinator libraries allow defining DSLs that embed in a host language. It provides examples of using F# to define DSLs for expressions, HTML, and forms. The document also discusses how F# features like algebraic data types and quotations enable easily defining and compiling DSLs to other languages.
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.
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
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
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
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
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
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