A very simple type check is not performed in F # ... why?

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 it puzzles me because it's not the age of a type test?

Also, is there a better way to compare types in F # .GetType() = typeof<> very long. I tried :? , but I think for typing, not for comparing types.

+4
source share
3 answers

The simple answer is, do the following:

 if (x :> obj) :? Test then printfn "true" else printfn "false" 

This problem arises due to the implementation of DU (using internal classes and tags) and the restriction of a system like F # (which does not confirm the implementation).

As you saw, type x is equal to FSI_0001+Test+Age , and F # does not recognize this as a subtype of Test .

+3
source

Quote from specification

The compiled union type U has:

. One CLI property for a static UC getter for each case with zero union C. This property gets a singleton object that represents each such case.

. One CLI-nested UC type for each case with non-zero union C. This type has instance properties Item1, Item2 .... for each case union field or a single property of an object if there is only one field. However, a compiled union type, which has only one case, does not have a nested type. Instead, the type of union itself plays the role of type.

We see that Age is implemented as a nested type of the parent DU. As a result, you can use Type.GetNestedTypes to get all the DU subtypes, and then check each one to see if the type matches.

+2
source

But it puzzles me because it's not a test like Color?

There is no type of Color , and Test is the type itself, so it has no type. Therefore, your question is meaningless.

Perhaps you wanted to ask why the answer is what it is? If so, this is a consequence of how F # currently prefers to represent such values โ€‹โ€‹internally.

-2
source

Source: https://habr.com/ru/post/1495219/


All Articles