tags:

views:

313

answers:

4

I've got an enumeration type defined like so:

type tags = 
    | ART  = 0
    | N    = 1
    | V    = 2 
    | P    = 3
    | NULL = 4

is there a way to do a for ... in tags do ?

This is the error that I'm getting:

The value, constructor, namespace or type tags is not defined

+2  A: 

Use Enum.GetValues:

let allTags = Enum.GetValues(typeof<tags>)
Jason
It should be Enum.GetValues(typeof<tags>). I had tried that earlier but didn't know of the different syntax for typeof. Thanks!
Jared
this won't work because tags is not an enum, it's an union...
Mauricio Scheffer
@Jason the code you first provided **did not** work against the code Jared posted. If another reader happened to bump into this question, he would have thought that Enum.GetValues could work with unions, which is not the case. Now that you explained I reverted my -1
Mauricio Scheffer
As a heads up, Enum.GetValues does not exist in the .NetCF or in the silverlight runtime.
RodYan
My problem with this is that GetValues will return an Array and I can't get it to cast back to an enum. I've tried `enum<tags> tag` but that didn't work.
Jared
+2  A: 

To make it an enum you need to explicitly give values to each case, otherwise it's a union type:

type tags = 
    | ART = 0
    | N = 1
    | V = 2
    | P = 3
    | NULL= 4
let allTags = System.Enum.GetValues(typeof<tags>)
Robert
+2  A: 

Robert's right about how to generate an actual enum and get its cases. If you have a true union type, you can get the cases via the Microsoft.FSharp.Reflection.FSharpType.GetUnionCases function.

kvb
+6  A: 

Here is a complete example that prints information about any discriminated union. It shows how to get cases of the discriminated union and also how to get the fields (in case you needed them). The function prints type declaration of the given discriminated union:

open System
open Microsoft.FSharp.Reflection

let printUnionInfo (typ:Type) = 
  printfn "type %s =" typ.Name
  // For all discriminated union cases
  for case in FSharpType.GetUnionCases(typ) do
    printf "  | %s" case.Name
    let flds = case.GetFields()
    // If there are any fields, print field infos
    if flds.Length > 0 then 
      // Concatenate names of types of the fields
      let args = String.concat " * " [ for fld in flds -> fld.PropertyType.Name ] 
      printf " of %s" args
    printfn ""    

// Example
printUnionInfo(typeof<option<int>>)
Tomas Petricek
The question was about enums, not discriminated unions.
Jason
The original type declaration in the post (before your edit) was a discriminated union though... Enums are of course useful in F# too, but in only a few situations.
Tomas Petricek
The only edit I made to the post was to fix a typo from "eumeration" to "enumeration." I think based on the subject that the OP always intended for the question to be about enums but introduced confusion in not correctly defining `tags` as an enum.
Jason
The original question was showing a discriminated union--not an enum. @Chris Smith added the " = <num>" to the original question after the fact and completely changed the type the original poster asked about. I'm not sure that was such a wise edit because it completely changes the nature of the question.
Onorio Catenacci
@Onorio Catenacci: I agree. There is definitely a lot of confusion as to what the OP meant. He stated "enumeration" in the subject, but defined a discriminated union in his post.
Jason
@Jason: Sorry, I didn't check the edits carefuly!
Tomas Petricek
@Tomas Petricek: No problem Tomas; there's just a lot of confusion here! By the way, I love your book Real-World Functional Programming.
Jason