This article is part of the F# Advent Calendar 2016
It is based on the first part of the ‘Build yourself a Robo-Advisor in F#’ workshop, as presented at the 2016 F# Progressive F# Tutorials conference in London.
Introduction
Most of us aren’t saving enough for our future. This isn’t something that’s going to go away - we’re living longer and many of us are underestimating how much money we need for a comfortable retirement. How can you solve this problem? By harnessing the power of F# to deliver clear and easy-to-understand advice and recommendations that takes you on a journey from confused to confident.
Over the last couple of years, robo-advisors have emerged as a platform for automating this advice as one part of the Fintech revolution. In this short series of posts we will build a web-based robo advisor that will show you how much money you might have in retirement.
Along the way you will discover how to:
- Understand a domain and model it with the F# type system
- Leverage F#’s data capabilities and make a first program that can chart our projected savings
- Take it to the next level by building a web-based robo-advisor using one of F#’s fantastic open-source web app frameworks
Part 1 - Domain modelling
A good first step towards building a new piece of software is to model the domain: what exactly is it we’re getting the software to do? What are the real-life equivalents of the code we want to write?
What is our domain?
We boil our domain down to one example question:
How much money will I have when I retire?
More generally, we want to take someone and calculate how much their pension pot will be worth when they retire.
The bold sections give us our basic domain:
- People
- Money
- Time
How can F# help us model it?
Algebraic Data Types
Discriminated Unions  allow us to express real-world concepts almost directly in code
Let’s take a really simple one with only two options, the boolean. How to we write this in F#?
type Bool = True | FalseWhat if we want to say that something can either have a value or not?
type Option<'a> = 
| Some of 'a
NoneWhat about if something can fail?
type Result<'TSuccess, 'TFailure> = 
| Succcess of 'TSuccess
| Failure of 'TFailureAnd what if we want to distinguish one type of string from another?
type EmailAddress = EmailAddress of stringThat’s all pretty useful! We can combin them with Records. Immutable records have a concise syntax and structural equality which make them really powerful for modelling. Here’s an example:
type Car = {
  Engine : Engine
  Wheels : Wheel list
  Seats : ... }Pattern matching
Once we have our unions, we have a type-safe switch alternative in the form of pattern matching. These give us a one-step match & decompose workflow, and for extra benefit the compiler catches non-exhaustive match so that we are warned if we’ve added a case and not properly handled it.
Here’s an example using a Result:
let handleResult = function
| Success result -> "Woop! It all worked, the answer is: " + result
| Failure error -> "Uh-oh. Something bad happened: " + errorUnits of measure
The question we want to answer here is:
How do you represent a currency in code?
One way to do so is with Units of Measure. With these we can make sure something has the right unit, as well as creating derives measures ( e.g kg m / s^2)
We can also reduce errors in conversions & calculations. How bad can this really be? Take a look here!
What did we come up with?
Using what we’ve just discussed, here’s a minimal domain model for figuring out how much money someone is likely to have in retirement.
module Domain =
  open System 
  type Gender = Male | Female
  type EmailAddress = EmailAddress of string
  type Person = { 
      Name : string
      Gender : Gender
      DateOfBirth : DateTime
      EmailAddress : EmailAddress option }
  type ContributionFrequency = Monthly | Annual
  type ContributionSchedule<[<Measure>] 'ccy> = {
      Amount : decimal<'ccy>
      Frequency : ContributionFrequency }
  type PensionPot<[<Measure>] 'ccy> = { 
      Value : decimal<'ccy>; 
      ValuationDate : DateTime; 
      ContributionSchedule: ContributionSchedule<'ccy> }
  [<Measure>] type GBP
  [<Measure>] type USD
  [<Measure>] type EUR
  let valuePensionPot<[<Measure>] 'ccy> (pensionPot : PensionPot<'ccy>) (valuationDate: DateTime) = 
     match pensionPot.ContributionSchedule.Frequency with 
     | Monthly ->
        let monthsInFuture = (valuationDate.Year - pensionPot.ValuationDate.Year) * 12 + valuationDate.Month - pensionPot.ValuationDate.Month
        pensionPot.Value + decimal monthsInFuture * pensionPot.ContributionSchedule.Amount
     | Annual ->
        let yearsInFuture = valuationDate.Year - pensionPot.ValuationDate.Year
        pensionPot.Value + decimal yearsInFuture * pensionPot.ContributionSchedule.AmountI think this code is pretty short and easy to understand given the complexity of the domain. We’ve used a wide variety of features that helped us along the way.
Useful links
Talks
Scott Wlaschin NDC: https://vimeo.com/97507575
Tomas Petricek Channel 9: https://www.youtube.com/watch?v=Sa6bntNslvY
Mark Seeman NDC: https://vimeo.com/131631483
Blogs
http://fsharpforfunandprofit.com/ddd/
http://tomasp.net/blog/type-first-development.aspx/
http://gorodinski.com/blog/2013/02/17/domain-driven-design-with-fsharp-and-eventstore/
Wrapping up
In this part you’ve seen how we take take a real-life domain and come up with a concise and accurate model for it using F#.
We’ve got some great language features to model domains in F#! If you are thinking about how to represent things in code, the ideas in this post are a great starting point.
Next time
Charts and data! You’ll see how to take the domain we’ve just created and chart it in a Desktop app with FSharp.Charting. We’ll also look at accessing data via type providers.
