Generics 枚举类型为的F#类型约束

Generics 枚举类型为的F#类型约束,generics,enums,f#,Generics,Enums,F#,我想写一个F#函数,它接受一个通用的枚举值,比如说,将其基础整数值加倍。幸运的是,有一个名为int的内置函数可以将枚举转换为整数,所以这应该很容易,对吗?这是我的第一次尝试: let doubler (value : 't when 't : enum<int>) = 2 * (int value) let doubler(值:'t when't:enum)= 2*(整数值) 遗憾的是,这会导致以下编译器消息: fs(2,10):警告FS0064:此构造导致代码 没有类型

我想写一个F#函数,它接受一个通用的枚举值,比如说,将其基础整数值加倍。幸运的是,有一个名为
int
的内置函数可以将枚举转换为整数,所以这应该很容易,对吗?这是我的第一次尝试:

let doubler (value : 't when 't : enum<int>) =
    2 * (int value)
let doubler(值:'t when't:enum)=
2*(整数值)
遗憾的是,这会导致以下编译器消息:

fs(2,10):警告FS0064:此构造导致代码 没有类型注释所指示的那么通用。类型变量 't已被约束为'int'类型

Program.fs(2,10):错误FS0071:应用时类型约束不匹配 类型推断变量的默认类型“int”。类型“int” 不是CLI枚举类型。另见Program.fs(1,28)-(1,42)。考虑 添加更多类型约束


我做错了什么?是否有更好的方法从F#中的通用枚举值中提取基础整数?

您需要
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
如果检查
倍频器的类型签名

val-doubler:xEnum:'a->int当'a:enum

关于您的第一个错误,
int
是特殊的,从某种意义上说,它也是一个函数。正如您所指出的,您可以在枚举中使用基础类型约束,但在这种情况下,请明确说明类型,这样就不会产生混淆:

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

不幸的是,如果不使用
EnumToValue
,您仍然无法强制转换到
int
。可能是编译器问题或其他问题。也许EnumToValue的内部可以给出一个提示?

enum所做的是将一个值转换为它的表示形式。编译器将为您输入约束。看下面。看起来很完美,谢谢。尽管如此,我的代码不起作用似乎还是很奇怪。@brianberns这是因为没有通用枚举(我想)。如果您想要约束,您需要说
let doubl2(x:'T when'T:enum)=
。但这将限制x仅为一种枚举类型。您仍然会遇到
int
问题。我不知道这个问题的根本原因。我的意思是没有什么像
enum
这样的东西。当然,您可以窃取类型签名,并将其显式化:
let tripler(xEnum:'a when'a:enum)=3*EnumToValue(xEnum)
。但是,即使没有它,编译器也会给您一个错误,例如char枚举。坦率地说,我真的没有必要在F#中使用enum,因为有du,可能除了命令行参数之外。我不明白你的意思。我很确定
enum
在F#中是一个合法的类型约束,尽管文档说它“不用于普通用途”。请参阅。关于这一点的另一个评论是:
EnumToValue
将枚举装箱,然后将其作为int解除装箱。这很好,但速度很慢。我真正想要的是性能和本机
int
操作符一样好的东西,它在运行时不需要循环。