Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不显式分配数字文字的情况下,用F#编写枚举?_F#_Enums - Fatal编程技术网

如何在不显式分配数字文字的情况下,用F#编写枚举?

如何在不显式分配数字文字的情况下,用F#编写枚举?,f#,enums,F#,Enums,我在F#中有一个枚举,如下所示: type Creature = | SmallCreature = 0 | MediumCreature = 1 | GiantCreature = 2 | HumongousCreature = 3 | CreatureOfNondescriptSize = 4 type Creature = | SmallCreature | MediumCreature | GiantCreature | Humon

我在F#中有一个枚举,如下所示:

type Creature =
   | SmallCreature = 0
   | MediumCreature = 1
   | GiantCreature = 2
   | HumongousCreature = 3
   | CreatureOfNondescriptSize = 4
type Creature =   
| SmallCreature   
| MediumCreature   
| GiantCreature   
| HumongousCreature   
| CreatureOfNondescriptSize

let input = int (System.Console.ReadLine())

let output = 
    match intToDU input with 
    | SmallCreature -> "Rat"    
    | Creature.MediumCreature -> "Dog"    
    | Creature.GiantCreature -> "Elephant"    
    | Creature.HumongousCreature -> "Whale"    
    | Creature.CreatureOfNondescriptSize -> "Jon Skeet"    
我不喜欢手动键入数字,我希望以后可以轻松地在枚举中插入更多项,而不必移动数字

我试过这个

type Creature =
   | SmallCreature
   | MediumCreature
   | GiantCreature
   | HumongousCreature
   | CreatureOfNondescriptSize
但它导致了一个错误
程序中稍后的类型“bioture”不是CLI枚举类型

let input = Int32.Parse(Console.ReadLine())
let output = match EnumOfValue<int, Creature>(input) with // <---Error occurs here
    | Creature.SmallCreature -> "Rat"
    | Creature.MediumCreature -> "Dog"
    | Creature.GiantCreature -> "Elephant"
    | Creature.HumongousCreature -> "Whale"
    | Creature.CreatureOfNondescriptSize -> "Jon Skeet"
    | _ -> "Unacceptably Hideous Monstrosity"

Console.WriteLine(output)
Console.WriteLine()
Console.WriteLine("Press any key to exit...")
Console.Read() |> ignore
let input=Int32.Parse(Console.ReadLine())
让输出=将EnumOfValue(输入)与//“Rat”匹配
|生物.媒介生物->“狗”
|生物。巨型生物->“大象”
|生物。巨大的生物->“鲸鱼”
|CreatureOfNondScriptSize->“Jon Skeet”
|——>“令人无法接受的可怕怪物”
控制台写入线(输出)
Console.WriteLine()
Console.WriteLine(“按任意键退出…”)
Console.Read()|>忽略

如何定义枚举而不为每个项目手动分配数值?

很遗憾,您不能。数值重要吗?如果是这样,它在某种程度上逃避了枚举的预期用途(撇开标志不谈)。在这种情况下,你可以考虑一个阶级或歧视联盟。 事实上,你的第二个例子是一个受歧视的联盟。但是您稍后使用的
EnumOfValue
(需要一个enum)导致了错误

另一个选项是将枚举到数字的映射存储在字典中,并用字典查找替换模式匹配。然后,枚举的数值将不相关


我同意手动管理枚举值是一项繁重的工作。我希望在将来的版本中解决这个问题。

正如Daniel所说,如果不指定数字等价物,就无法定义枚举。但是,您可以定义一个函数,该函数将数字转换为区分并集的对应情况:

open Microsoft.FSharp.Reflection

let intToDU<'t> n =
    if not (FSharpType.IsUnion typeof<'t>) then
        failwithf "%s is not a discriminated union" typeof<'t>.Name
    let cases = FSharpType.GetUnionCases(typeof<'t>)
    if n >= cases.Length || n < 0 then
        failwithf "%i is out of the range of %s's cases (0 - %i)" n typeof<'t>.Name (cases.Length - 1)
    let uc = cases.[n]
    if uc.GetFields().Length > 0 then 
        failwithf "%s.%s requires constructor arguments" typeof<'t>.Name uc.Name
    FSharpValue.MakeUnion(uc, [||]) :?> 't

这还有一个额外的好处,即模式匹配现在是完全匹配的。

是否有任何方法可以获取C#中可见的
标记
内部类(或案例中的
标记
属性)?这将使这不需要使用反射而成为可能。@Daniel-据我所知不是这样。但是,我看不出这有什么帮助:您可以使用标记值将DU转换为int,但不能将DU转换为int(除非我遗漏了什么)。从int转换为DU仍然需要一个函数,但这可以在没有反射的情况下完成,或者不依赖于大小写顺序。这不会是一个巨大的进步。我只是好奇。你知道有没有计划解决这个问题?可能是
[]
属性?:-)我想这仍然会给DUs留下语法上的歧义。也许一个
[]
属性可以解决这个问题,就像
[]
解决接口的不确定性一样。@Daniel-我不知道是否有计划解决这个问题,但我从来没有发现它特别繁重——通常我更喜欢DUS,因为它们给了你完全匹配。虽然我不认为DUS是枚举替换中的一个掉落,但是如果你走那个路线,你可能会考虑标记你的类型,因为DU事例是封闭的命名空间的顶层成员。