2017-02-21 5 views
2

Я хотел бы написать функцию F #, которая принимает общее значение перечисления и, скажем, удваивает его базовое целочисленное значение. К счастью, есть встроенная функция, называемая int, которая преобразует перечисление в целое число, поэтому это должно быть легко, не так ли? Вот моя первая попытка:Ограничение типа F # с типом Enum

let doubler (value : 't when 't : enum<int>) = 
    2 * (int value) 

К сожалению, это приводит следующие сообщения компилятора:

Program.fs (2,10): предупреждение FS0064: Эта конструкция вызывает код быть меньше общего, чем обозначенных аннотациями типа. Переменная типа 't была ограничена типом' int '.

Program.fs (2,10): error FS0071: Несоответствие ограничения типа при применении по умолчанию типа 'int' для переменной ввода типа. Тип 'int' не является типом перечисления CLI. См. Также Program.fs (1,28) - (1,42). Рассмотрим , добавив дополнительные ограничения типа

Что я делаю неправильно? Есть ли лучший способ извлечь базовое целое из общего значения перечисления в F #?

+0

Что означает 'enum', это преобразование значения в его представление. Компилятор предоставит вам ограничение. Смотри ниже. – s952163

ответ

1

Необходимо EnumToValue.

open FSharp.Core.LanguagePrimitives 

let doubler xEnum = 
     2 * EnumToValue(xEnum) 

type ColorEnum =  
      | Red=0 
      | Yellow=1 
      | Blue=2 

let blue = ColorEnum.Blue 

doubler blue 
//val it : int = 4 

И если вы исследуете тип подписи doubler:

вал удвоитель: xEnum: 'а -> Int когда' а: перечислимую

Что касается вашей первой ошибки, int является особенным, в некотором смысле, что это тоже функция. Как вы отмечаете, вы можете использовать базовый тип ограничения в перечислении, но в этом случае быть явным о типе, так что нет никакой путаницы:

let double2 (x:'T when 'T:enum<int32>) = 
    2 * EnumToValue(x) 

К сожалению, вы все равно не в состоянии бросить в int без использования EnumToValue. Может быть проблема с компилятором или что-то еще. Может быть, внутренности EnumToValue могут дать подсказку?

+0

Это выглядит отлично, спасибо. Тем не менее кажется странным, что мой код не работает. – brianberns

+0

@brianberns Это потому, что нет общего Enum (я думаю). Если вы хотите ограничить, вам нужно сказать 'let doubl2 (x: 'T, когда' T: перечисление ) ='. Это ограничило бы x только одним типом Enum. И вы все равно столкнетесь с проблемой 'int'. Я не знаю причину этого. – s952163

+0

Я имею в виду, что нет такой вещи, как 'enum '. Вы могли бы, конечно, украсть подпись типа и сделать ее явной: 'let tripler (xEnum: 'a when' a: enum <_>) = 3 * EnumToValue (xEnum)'. Но даже без него компилятор даст вам ошибку, например, с перечислениями символов. Чтобы быть откровенным, мне не нужно было использовать перечисления в F #, потому что есть DU, возможно, кроме аргументов командной строки. – s952163