How to enumerate an enum/type in F# tells us how to get an enumerator for a .Net enum type in F#:
Use: Enum.GetValues(typeof<MyType>)
However, when I put that into use I found a limitation. I can work around that limitation, but I am looking for a better way.
The problem is that the solution returns a .Net Array of Objects, but to use it we need to cast it, and that casting is unwieldy for iteration.
type Colors =
| Red = 0
| Blue = 1
| Green = 2
// Strongly typed function, to show the 'obj' in real use
let isFavorite color = color = Colors.Green
// Iterate over the Enum (Colors)
for color in Enum.GetValues(typeof<Colors>) do
printfn "Color %A. Is Favorite -> %b" color (isFavorite color) // <-- Need to cast
The (IsFavorite color)
raises a type conflict between Colors
(expected) and obj
(actual)
This is easily fixed:
for obj in Enum.GetValues(typeof<Colors>) do
printfn "Color %A. Is Favorite -> %b" obj (isFavorite (unbox<Colors> obj))
But, what if one needs that (unbox<Colors> obj)
in several places?
A local let color = ...
will suffice, but, ideally, we would use an enumerable-expression which returns a seq<Colors>
.
I have been able to build that expression, but it is: a. difficult to build, and b. long winded.
let colorsSeq =
Seq.cast (Enum.GetValues(typeof<Colors>))
|> Seq.map (fun o -> unbox<Colors> o)
for color in colorsSeq do
printfn "Color %A. Is Favorite -> %b" color (isFavorite color)
Is there a better expression?
Enum.GetValues
is an old BCL API, so there's nothing much you can do about it... I don't think you can get what you want in a significantly more concise way than what you already have, but you can reduce it a bit:
let colorsSeq = Enum.GetValues(typeof<Colors>) |> Seq.cast<Colors>
If you need to do something like this a lot, you could consider packaging it in a generic function:
module Enum =
let values<'a> = Enum.GetValues(typeof<'a>) |> Seq.cast<'a>
Which would enable you to use it like this:
for color in Enum.values<Colors> do
printfn "Color %A. Is Favorite -> %b" color (isFavorite color)
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