I want to write something like this:
type NumExp = Num of float
type Exp =
| Num of float
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
let getValue (Num(n) : NumExp) = n
The compiler complains about a conflict between NumExp and Exp in getValue.
Even the following fails:
let getValue (nn : NumExp) = match nn with | Num(n) -> n
Is there a way to use the same case in both discriminated unions that works with functions? The DU definitions themselves are OK.
I want to use the same case to avoid adding a level of indirection like
type Exp =
| NumExpExp of NumExp
| Dot of NumExp * NumExp
| Op of string * Exp * Exp
in the Exp definition.
I feel I’m missing something very basic here.
The reason I have NumExp is that I want to be able to ‘plug’ 2 Exps into a Dot (rather than 2 floats) because it makes generating expressions easier, but they can’t be any Exp, just numerical.
EDIT: what I really wanted to know is whether the two cases in the two DUs could be treated as the same entity (kind of like Exp “including” NumExp). I realise now Exp.Num and NumExp.Num are completely separate entities. Tomas provides a nice way of discriminating the two cases below.
If you have two discriminated unions with conflicting names of cases, you can use fully qualified name of the discriminated union case:
A more complete example would look like this:
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
Expthat simply includes values ofNumExp. For example like this:When writing
evalfunction you would then write (note that we no longer have the issue with name clashes, so we don’t need fully qualified names):