问题
I would like to write an F# function that takes a generic enum value and, let's say, doubles its underlying integer value. Fortunately, there's a built-in function called int
that converts an enum to an integer, so this should be easy, right? Here's my first attempt:
let doubler (value : 't when 't : enum<int>) =
2 * (int value)
Sadly, this results in the following compiler messages:
Program.fs(2,10): warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 't has been constrained to be type 'int'.
Program.fs(2,10): error FS0071: Type constraint mismatch when applying the default type 'int' for a type inference variable. The type 'int' is not a CLI enum type. See also Program.fs(1,28)-(1,42). Consider adding further type constraints
What am I doing wrong? Is there a better way to extract the underlying integer from a generic enum value in F#?
回答1:
You need 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
And if you examine the type signature of the doubler
:
val doubler : xEnum:'a -> int when 'a : enum
Regarding your first error, int
is special, in a sense that it's a function as well. As you point out, you can use an underlying type constraint in the enum, but in that case be explicit about the type, so there is no confusion:
let double2 (x:'T when 'T:enum<int32>) =
2 * EnumToValue(x)
Unfortunately you will still not be able to cast to int
without using EnumToValue
. Could be a compiler issue, or something else. Maybe the internals of EnumToValue can give a hint?
来源:https://stackoverflow.com/questions/42357587/f-type-constraint-with-enum-type