2010-02-02 57 views
9

我有一個枚舉型定義,像這樣的枚舉/類型:如何枚舉在F#

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

有沒有辦法做一個for ... in tags do

這是我得到的錯誤:

值,構造函數,命名空間或 類型tags沒有定義

+2

這不是一個枚舉,它是一個聯合。 –

+0

如果您需要枚舉,請參閱http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc245030918 –

回答

5

使用Enum.GetValues

let allTags = Enum.GetValues(typeof<tags>) 
+0

它應該是Enum.GetValues(typeof )。我曾經嘗試過,但不知道typeof的不同語法。謝謝! – Jared

+3

這不會工作,因爲標籤不是一個枚舉,它是一個聯合... –

+0

你第一次提供的代碼**沒有**工作對Jared發佈的代碼。如果另一位讀者遇到這個問題,他會認爲Enum.GetValues可以與工會合作,事實並非如此。現在你已經解釋了我已經恢復了我的-1 –

2

要使它成爲一個枚舉,你需要明確地給每個案例賦值,否則它是一個union類型:

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

羅伯特的權利關於如何生成一個實際枚舉和得到它的情況。如果你有一個真正的工會類型,你可以通過Microsoft.FSharp.Reflection.FSharpType.GetUnionCases功能獲得案例。

6

這裏是一個完整的例子,打印有關任何歧視聯盟的信息。它展示瞭如何獲得歧視工會的案例,以及如何獲得這些領域(以防你需要他們)。給定的區分聯合的功能打印類型聲明:

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>>) 
+0

問題是關於枚舉,而沒有受到歧視的工會。 – jason

+2

在帖子中的原始類型聲明(在您編輯之前)是一個有歧視的聯盟,儘管...枚舉在F#中當然也是有用的,但在少數情況下也是如此。 –

+0

我對這篇文章的唯一編輯就是修正了一個從「eumeration」到「enumeration」的錯字。我認爲OP的基礎是OP始終打算將這個問題作爲關於枚舉的問題,但引入了將'tags'作爲枚舉正確定義的混淆。 – jason

1

您可以使用Enum.GetValues,它返回的對象就是你必須向下轉型爲整數值的Array。 (注:我使用的是單聲道的F#的實現;也許事情是與.NET不同)

這裏有一些功能,我寫來獲取所有枚舉值的列表,並獲得了最小值和最大值:

open System 

module EnumUtil = 

    /// Return all values for an enumeration type 
    let EnumValues (enumType : Type) : int list = 
     let values = Enum.GetValues enumType 
     let lb = values.GetLowerBound 0 
     let ub = values.GetUpperBound 0 
     [lb .. ub] |> List.map (fun i -> values.GetValue i :?> int) 

    /// Return minimum and maximum values for an enumeration type 
    let EnumValueRange (enumType : Type) : int * int = 
     let values = EnumValues enumType 
     (List.min values), (List.max values) 
0
type Options = 
    | Exit   = 0 
    | CreateAccount = 1 

Console.WriteLine() 
Console.WriteLine("Choose an option:") 
let allOptions = Enum.GetValues(typeof<Options>) 
for option in allOptions do 
    if (option <> null) then 
     Console.WriteLine(sprintf "%d: %s" (option :?> int) (option.ToString())) 
let optionChosen = System.Console.ReadLine()