On day 1 of the Progressive F# Tutorials in NYC on the beginner’s track we started with the F# Koans to introduce F#’s syntax and language features, and then finished up with F# Katas to put some of that learning into practice.
On day 2 the idea was to look at how to structure F# programs through a tutorial on Domain-specific languages (DSLs) in F#, and finish up the day with a fun programming contest.
DSLs
Here are the slides, they’re a little sparse as most of the session was a hands-on tutorial with live code examples:
DSL: UML Sequence Diagrams
This sample shows how easy it is to create an internal DSL in F#:
type Object(name) = member o.Name = name
type Action = Action of string * Object * Object
let fred = Object("Fred")
let bob = Object("Bob")
let hank = Object("Hank")
let renee = Object("Renee")
let (--) (source:Object) (message:string) =
(source,message)
let (-->) (source:Object,action:string) (target:Object) =
Action(action,source,target)
let actions =
[
fred -- "order food" --> bob
bob -- "serve wine" --> fred
hank -- "pickup" --> bob
bob -- "serve food" --> fred
fred -- "pay" --> renee
]
The sample above uses a single line to define an class for specifying object’s and their associated names, and another line using a discriminated union to define actions between objects. Custom operators are used to allow the actions to be defined in a way that is similar to drawing in a UML Sequence diagram
DSL: Retail Domain
Next up we created a simple domain for Retail Point-of-Sale (POS) application:
type Code = string
type Name = string
type Price = decimal
type Product = Product of Code * Name * Price
type Quantity = decimal
type LineNo = int
type LineItem =
| SaleLineItem of LineNo * Product * Quantity
| TenderLineItem of Tender * Price
| CancelLineItem of LineNo
Then used it to build a simple command line based Retail application that could lookup items from a barcode scanner and show a total on checkout.
There are some exercises to work through in the attached code.
DSL: Automated Acceptance Testing with TickSpec
Before the break I gave a brief introduction to TickSpec an F# library for automating acceptance tests. TickSpec allows you to wire up English language test specifications to your code in a variety of ways including regular expressions.
DSL: Fluent API for Unit Testing
Tomas led a session on building a fluent API using the example of unit testing:
[<Test>]
let ``Sum of 1 to 5 is 15``() =
[ 1 .. 5 ] |> sum
|> should equal 15
In this session Tomas managed to introduce a new custom operator (+/-) which lets you concisely declare range checks:
value should equal 7.0 (+/-) 0.000001
DSL: Spreadsheet
Finally we looked at how to create an external DSL using a Spreadsheet as an example. If you’re interested in learning more I’d recommend looking through these articles:
Mystery Coding Contest
The mystery coding contest was an ant colony simulator where you had to implement an AI for ants to beat a rival colony, which involved attacking the enemy, searching for food, leaving pheromone trails.
Read more over on Rich Minerich’s blog