So I have this code:
type Zero = One = 1 | Two = 2 | Three = 3
type Four = Five = 5 | Six = 6 | Seven = 7
let test_1 (x : bool) : Type =
if x
then typeof<Zero>
else typeof<Four>
let test_2 () =
let ty = test_1 true
let e = enum<ty>(1)
...
However on the last line, I get an error: Type ty not defined.
Any suggestions?
Edit:
Or maybe something like this:
let test_3 (x : bool) (i : int) : obj =
if x
then enum<Zero>(i) :> obj
else enum<Four>(i) :> obj
I was thinking would there be some way to regain type safety?
Maybe something like this?
let test_4 (x : bool) (i : int) : obj * Type =
if x
then enum<Zero>(i) :> obj, typeof<Zero>
else enum<Four>(i) :> obj, typeof<Four>
Then use it as so:
let test_5 () =
let v,t = test_4 true 1
let o = v :?> t
...
This complains on the last line with t not defined.
Basically what I'm trying to do is to be able to return these different enums without resorting to wrapping Zero and Four into a DU.
You can't do that, "type safety" implies you (the compiler) know the type statically (without executing code). By casting to obj
you loose that knowledge. Adding a runtime type (typeof
) does not help. Even if you could use the second value of the returned tuple, how would that help? Your program code would be hard-coded for whatever true|false
value you had.
If this value is not known at compile time (e.g. read from console), what type would you assume? What should t
be in the following binding?
let o : t = test someBool someInt
It could be either Zero
or Four
, that is Zero | Four
, that is type Either = Zero | Four
, that is
type EitherEnum =
| Z of Zero
| F of Four
... a discriminated union, as you figured out already.
Basically what I'm trying to do is to be able to return these different enums without resorting to wrapping Zero and Four into a DU.
You figured out how to do that already: cast to obj
and loose type safety. You can't have it both ways.
What you are looking for are dependent types, something e.g. F* provides.