I'm trying to get my head around discriminated unions and record types; specifically how to combine them for maximum readability. Here's an example - say a sports team can either have points (both league points and goal difference), or it can be suspended from the league in which case it has no points or goal difference. Here's how I tried to express that:
type Points = { LeaguePoints : int; GoalDifference : int }
type TeamState =
| CurrentPoints of Points
| Suspended
type Team = { Name : string; State : TeamState }
let points = { LeaguePoints = 20; GoalDifference = 3 }
let portsmouth = { Name = "Portsmouth"; State = points }
The problem comes at the end of the last line, where I say 'State = points'. I get 'Expression was expected to have type TeamState but here has type Points'. How do I get around that?
To add some details to pad's answer, the reason why your initial version did not work is that the type of value assigned to State
should be a discriminated union value of type TeamState
. In your expression:
let portsmouth = { Name = "Portsmouth"; State = points }
...the type of points
is Points
. In the version posted by pad, the expression CurrentPoints points
uses a constructor of TeamState
to create a discriminated union value representing CurrentPoints
. The other option that the union gives you is Suspended
, which can be used like this:
let portsmouth = { Name = "Portsmouth"; State = CurrentPoints points }
let portsmouth = { Name = "Portsmouth"; State = Suspended }
If you did not use the name of the constructor, then it is not clear how you'd construct a suspended team!
Finally, you can also write everything on just a single line, but that's not as readable:
let portsmouth =
{ Name = "Portsmouth"
State = CurrentPoints { LeaguePoints = 20; GoalDifference = 3 } }
let portsmouth = { Name = "Portsmouth"; State = CurrentPoints points }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With