val timesTable : n:'a -> 'b

Full name: index.timesTable
val n : 'a
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>

DSLs for HTML / XML with F# Combinator Library

  • What is a DSL?
  • What is a Combinator Library?
  • HTML DSL
  • XML DSL with CSV Type Provider
  • HTML tree structure
  • Discrimated Union for data tree structure
  • Combinator Library
  • Quotes on functional programming
  • Combinator Library products

What is a DSL?

A domain specific language (DSL): is a programming language tailored for a particular application domain, which captures precisely the semantics of the application domain.

What is a Combinator Library?

A combinatory library offers functions (the combinators) that combine functions together to make bigger functions. These kinds of libraries are particularly useful for allowing domain-specific programming languages to be easily embedded into a general purpose.

HTML DSL

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
let timesTable n =
html []
    [
    head [] [title [] %(sprintf "%d Times table" n)]
    body [] 
        [
        h1 [] %(sprintf "%d Times table" n)
        ul [] 
            [
            for i in 1..12 -> 
                li [] 
                %(sprintf "%d x %d = %d" n i (n*i))]
        ]
    ]
timesTable 17 |> HtmlToString

HTML output

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
<html>
    <head>
        <title>17 Times table</title>
    </head>
    <body>
        <h1>17 Times table</h1>
        <ul>
            <li>17 x 1 = 17</li>
            <li>17 x 2 = 34</li>
            ...
            <li>17 x 11 = 187</li>
            <li>17 x 12 = 204</li>
        </ul>
    </body>
</html>

CSV Type Provider and XML DSL

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
[<Literal>]
let filePath = __SOURCE_DIRECTORY__+ @"\msft.csv"
type Stocks = CsvProvider<filePath>
let msft = Stocks.Load(filePath)

xml []
[ 
    for row in msft.Rows ->
    value 
        [
        date (row.Date.ToString("yyyyMMdd"))
        high (string(row.High.ToString("N2")))
        ]
        %(string(row.Close.ToString("N2")))
]
|> XmlToString

XML output

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
<xml>
 <value Date="20170216" High="65.24">64.52</value>
 <value Date="20170215" High="64.57">64.53</value>
 <value Date="20170214" High="64.72">64.57</value>
 <value Date="20170213" High="64.86">64.72</value>
 ...
 <value Date="19860317" High="29.75">29.50</value>
 <value Date="19860314" High="29.50">29.00</value>
 <value Date="19860313" High="29.25">28.00</value>
</xml>

HTML sample

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
<html xmlns="http://www.w3.org/1999/xhtm">
    <head>
        <title>GDNUG Talk</title>
    </head>
    <body>
        <h1>Hello world!</h1>
        <form id="form1">
            <input type="text" name="name" />
        </form>
    </body>
</html>

Data tree structure

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
- Tag: html
    - Attr: xmlns "http://www.w3.org/1999/xhtm"
    - Tag: head
        - Tag: title
            - Text: GDNUG Talk
    - Tag: body
        - Tag: h1
            - Text: Hello world!
        - Tag: form
            - Attr: id form1
            - Tag: input
                -Attr: type text
                -Attr: name name

We need to be able to generate and manipulate this tree in an abstract, type safe way

Discrimated Unions

From the MSDN page for Discriminated Unions:

Discriminated unions provide support for values that can be one of a number of named cases, possibly each with different values and types.

Used in particular for :

  • object hierarchies
  • tree data structures

Discrimated Unions for HTML

1: 
2: 
3: 
4: 
type Html =
    | Text of string
    | Attr of string * string
    | Tag of string * Html list * Html list

The cases Text, Attr and Tag provide:

  • functions to create the different cases
  • pattern matching

First version of HTML sample: coding

Combinator Library

Function to simplify the creation of Html elements:

1: 
2: 
3: 
let tag name attrs elems = Tag(name, attrs, elems)
let (%=) name value = Attr(name,value)
let (~%) s = [Text(s.ToString())]

Second version of HTML sample: coding

Combinator Library

DSL functions:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let html attrs elems = tag "html" attrs elems
let head attrs elems = tag "head" attrs elems
let title attrs elems = tag "title" attrs elems
let body attrs elems = tag "body" attrs elems
let h1 attrs elems = tag "h1" attrs elems
let form attrs elems = tag "form" attrs elems  
let input attrs elems = tag "input" attrs elems  

Third and final version of HTML sample: coding

Question: How to do the same in POO language?

Quotes on functional programming

Combinator Library products

  • FParsec: a parser combinator library for F#.
  • WebSharper: a fundamentally different web framework for developing functional and reactive .NET applications
  • Suave: a simple web development F# library providing a set of combinators to manipulate route flow and task composition.
  • Composing contracts: an adventure in financial engineering: a fundamentally different web framework for developing functional and reactive .NET applications