I am working on a new version of the Spiral language and as one of its features, it will have structural equality and comparison similar to F#. But I am having difficulty figuring out how to compile that efficiently to F#.
The problem is that I cannot find how F# exposes tag information for its union cases.
For example, if I wrote cmp a b I'd like the Spiral compiler to generate something like the following F# code.
type T =
| A of int32
| B of float
let cmp_t = function
| A x, A x' -> cmp_i32 (x, x')
| B x, B x' -> cmp_f64 (x, x')
| x, x' -> cmp_i32 (union_tag x, union_tag x')
I've looked around and there are some proposals to expose the tag information, but nothing is out yet. I am wondering whether the F# compiler library has some functionality that I am not aware of for extracting the tag.
Otherwise for every union type, I am going to have to generate a custom tag function like...
let tag_t = function
| A _ -> 0
| B _ -> 1
But this can't be the right choice because F# has to be using some kind of tag under the hood for each of the union cases in order to differentiate them. It has to be able to know the tag for its own comparison function. Making tag functions like these would bloat the generated code and would be inefficient at runtime.
What should I do here?