F# and statically checked union cases
- by Johan Jonasson
Soon me and my brother-in-arms Joel will release version 0.9 of Wing Beats. It's an internal DSL written in F#. With it you can generate XHTML. One of the sources of inspiration have been the XHTML.M module of the Ocsigen framework. I'm not used to the OCaml syntax, but I do understand XHTML.M somehow statically check if attributes and children of an element are of valid types.
We have not been able to statically check the same thing in F#, and now I wonder if someone have any idea of how to do it?
My first naive approach was to represent each element type in XHTML as a union case. But unfortunately you cannot statically restrict which cases are valid as parameter values, as in XHTML.M.
Then I tried to use interfaces (each element type implements an interface for each valid parent) and type constraints, but I didn't manage to make it work without the use of explicit casting in a way that made the solution cumbersome to use. And it didn't feel like an elegant solution anyway.
Today I've been looking at Code Contracts, but it seems to be incompatible with F# Interactive. When I hit alt + enter it freezes.
Just to make my question clearer. Here is a super simple artificial example of the same problem:
type Letter =
| Vowel of string
| Consonant of string
let writeVowel =
function | Vowel str -> sprintf "%s is a vowel" str
I want writeVowel to only accept Vowels statically, and not as above, check it at runtime.
How can we accomplish this? Does anyone have any idea? There must be a clever way of doing it. If not with union cases, maybe with interfaces? I've struggled with this, but am trapped in the box and can't think outside of it.