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