I'm trying to define a generic conversion operator from a string to an Enum, and I'd like to use it like this:
let day = asEnum<DayOfWeek>("Monday")
But with this implementation:
let asEnum<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<'b>> text =
match Enum.TryParse<'a>(text) with
| true, value -> Some value
| false, _ -> None
I can only use it like this:
let day = asEnum<DayOfWeek,_>("Monday")
or this:
let day:DayOfWeek option = asEnum("Monday")
If I omit the 'a : enum<'b>
altogether from the type constraint, I can have it as I want, but then if someone doesn't specify the type it will default to int
, which I really don't like, I'd prefer it to give a compile time error like it does when I specify a constraint
Maybe there's any trick to just specify one type parameter and have the other one infered? Any ideas?
Unfortunately, in order to augment the constraint it seems you have to spell it all out: (as kvb pointed out, you can avoid duplicating the constraints on TryParse
by adding the 'T : enum<int>
constraint outside the angle brackets)
This also works:
let asEnum<'T
when 'T : enum<int>
and 'T : struct
and 'T :> ValueType
and 'T : (new : unit -> 'T)> text =
match Enum.TryParse<'T>(text) with
| true, value -> Some value
| _ -> None
This gives a compile-time error if the underlying type isn't int
:
type ByteEnum =
| None = 0uy
asEnum<ByteEnum> "None" //ERROR: The type 'int' does not match the type 'byte'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With