Reputation: 31546
I wrote this code
type Test =
| Age of int
| Name of string;;
let x = Age(10);;
if (x.GetType() = typeof<Test>) then printfn "true" else printfn "false";;
The code prints false. But that puzzles me because isn't Age of type Test?
Also, is there a better way to compare types in F# the .GetType() = typeof<>
is very long. I tried :?
but I think that's for typecasting rather than comparing types.
Upvotes: 4
Views: 871
Reputation: 48687
But that puzzles me because isn't Test of type Color?
There is no type Color
and Test
is a type itself so it does not have a type. So your question is nonsensical.
Perhaps you meant to ask why the answer is what it is? If so, it is a consequence of the way F# currently chooses to represent such values internally.
Upvotes: -2
Reputation: 25516
Quoting from the spec
A compiled union type U has:
· One CLI static getter property U.C for each null union case C. This property gets a singleton object that represents each such case.
· One CLI nested type U.C for each non-null union case C. This type has instance properties Item1, Item2.... for each field of the union case, or a single instance property Item if there is only one field. However, a compiled union type that has only one case does not have a nested type. Instead, the union type itself plays the role of the case type.
We see that Age
is implemented as a nested type of the parent DU. As a result you could use Type.GetNestedTypes
to get all the subtypes of the DU and then test each one to see if the type matches.
Upvotes: 2
Reputation: 7560
The plain answer is, do so:
if (x :> obj) :? Test then printfn "true" else printfn "false"
This issue comes because of the implementation of DUs (using internal classes and tags) and the limitation of F#'s type system (which does not acknowledge the implementation).
As you saw, the type of x
is FSI_0001+Test+Age
, and F# does not recognize that as a sub-type of Test
.
Upvotes: 4