Функция, возвращающая тип, используемый в функции, принимающей параметр универсального типа

Итак, у меня есть этот код:

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)
     ...

Однако в последней строке я получаю сообщение об ошибке: Type ty not defined.

Какие-либо предложения?

Редактировать:

Или, может быть, что-то вроде этого:

let test_3 (x : bool) (i : int) : obj =
    if x
    then enum<Zero>(i) :> obj
    else enum<Four>(i) :> obj

Я думал, есть ли способ восстановить безопасность типов?

Может быть, что-то вроде этого?

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>

Затем используйте его так:

let test_5 () =
    let v,t = test_4 true 1
    let o = v :?> t
    ...

Это жалуется на последнюю строку с не определенным t.

В основном то, что я пытаюсь сделать, - это иметь возможность возвращать эти разные перечисления, не прибегая к обертыванию Zero и Four в DU.


person Aistis Raulinaitis    schedule 18.02.2017    source источник
comment
Параметры типа должны быть известны статически, они не могут быть результатом динамических вычислений.   -  person kvb    schedule 18.02.2017
comment
Экземпляр Type существует во время выполнения; enum ожидает аргумент времени компиляции.   -  person ildjarn    schedule 18.02.2017


Ответы (1)


Вы не можете этого сделать, «безопасность типов» подразумевает, что вы (компилятор) знаете тип статически (без выполнения кода). Применяя к obj, вы теряете это знание. Добавление типа runtime (typeof) не помогает. Даже если бы вы могли использовать второе значение возвращаемого кортежа, как бы это помогло? Ваш программный код будет жестко закодирован для любого значения true|false, которое у вас есть.

Если это значение неизвестно во время компиляции (например, чтение из консоли), какой тип вы бы предположили? Что должно быть t в следующей привязке?

let o : t = test someBool someInt

Это может быть либо Zero, либо Four, то есть Zero | Four, то есть type Either = Zero | Four, то есть

type EitherEnum =
| Z of Zero
| F of Four

... дискриминированный союз, как вы уже поняли.

В основном то, что я пытаюсь сделать, - это иметь возможность возвращать эти разные перечисления, не прибегая к обертыванию Zero и Four в DU.

Вы уже поняли, как это сделать: привести к obj и потерять безопасность типов. У вас не может быть и того, и другого.

То, что вы ищете, это зависимые типы, что-то, например. F* обеспечивает.

person CaringDev    schedule 18.02.2017