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
objyou 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 whatevertrue|falsevalue you had.If this value is not known at compile time (e.g. read from console), what type would you assume? What should
tbe in the following binding?It could be either
ZeroorFour, that isZero | Four, that istype Either = Zero | Four, that is... a discriminated union, as you figured out already.
You figured out how to do that already: cast to
objand loose type safety. You can't have it both ways.What you are looking for are dependent types, something e.g. F* provides.