简体   繁体   中英

Function returning type used in a function taking a generic type parameter

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 (eg 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 Zero | Four , that is type Either = Zero | Four 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 eg F* provides.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM