If you have two discriminated unions with conflicting names of cases, you can use fully qualified name of the discriminated union case:
let getValue (NumExp.Num(n)) = n
A more complete example would look like this:
let rec eval = function
| Exp.Num(f) -> f
| Exp.Dot(NumExp.Num(f1), NumExp.Num(f2)) ->
// whatever 'dot' represents
| Exp.Op(op, e1, e2) ->
// operator
This always uses fully qualified names, which is probably a good idea if the names are simple enough and there are conflicting cases (which could lead to a confusion).
EDIT: Regarding sharing of cases - there is no automatic way of doing that, but you could have a case in your Exp
that simply includes values of NumExp
. For example like this:
type NumExp =
| Num of float
type Exp =
// first occurrence of NumExp is just a name, but F# allows us to reuse
// the name of the type, so we do that (you could use other name)
| NumExp of NumExp
// other cases
When writing eval
function you would then write (note that we no longer have the issue with name clashes, so we don't need fully qualified names):
| NumExp(Num f) -> f
| Op(op, e1, e2) -> // ...