如何枚举F#中受歧视联盟的可能“价值”?
我想知道对于受歧视的工会是否有类似Enum.GetValues(Type)
的东西,我很难确定我会列举哪种数据。我想为每个选项生成一个带有区别联合的列表或数组,其中包含一个项目。
答案 0 :(得分:36)
是的,F#在.NET的反射之上有自己的反射层构建,以帮助您理解特定于F#的类型,如区分联合。这是允许您枚举联合案例的代码:
open Microsoft.FSharp.Reflection
type MyDU =
| One
| Two
| Three
let cases = FSharpType.GetUnionCases typeof<MyDU>
for case in cases do printfn "%s" case.Name
答案 1 :(得分:9)
稍微扩展Robert的示例 - 即使您没有受歧视联合的实例,也可以使用F#反射来获取有关类型的信息(例如 types < / em>个案的论据)。以下扩展了Robert的示例,它还打印了参数的类型:
open Microsoft.FSharp.Reflection
let ty = typeof<option<int>>
let cases = FSharpType.GetUnionCases ty
printfn "type %s =" ty.FullName
for case in cases do
printf "| %s" case.Name
let fields = case.GetFields()
if fields.Length > 0 then
printf " of"
for fld in fields do
printf " %s " fld.PropertyType.FullName
printfn ""
例如,对于option<int>
类型,您将得到(我稍微简化了输出):
type Microsoft.FSharp.Core.FSharpOption`1[System.Int32] =
| None
| Some of System.Int32
此信息有许多有趣的用途 - 例如,您可以从F#联合生成数据库模式,或创建将XML解析为区分联合(描述结构)的函数。我谈到了XML processing sample at GOTO conference earlier this year。
答案 2 :(得分:6)
如果您的歧视联盟仅由普通标识符组成(不存储任何数据,则可能是您需要的:gist
open Microsoft.FSharp.Reflection
module SimpleUnionCaseInfoReflection =
// will crash if 'T contains members which aren't only tags
let Construct<'T> (caseInfo: UnionCaseInfo) = FSharpValue.MakeUnion(caseInfo, [||]) :?> 'T
let GetUnionCaseInfoAndInstance<'T> (caseInfo: UnionCaseInfo) = (caseInfo, Construct<'T> caseInfo)
let AllCases<'T> =
FSharpType.GetUnionCases(typeof<'T>)
|> Seq.map GetUnionCaseInfoAndInstance<'T>
#load "SimpleUnionCaseInfoReflection.fs"
type Foos = Foo | Bar | Baz
SimpleUnionCaseInfoReflection.AllCases<Foos> |> Seq.iter (fun (caseInfo, instance) ->printfn "name: %s instance: %O is Bar? : %b" caseInfo.Name instance (instance.Equals(Foos.Bar)))
(*
> name: Foo instance: FSI_0055+Foos is Bar? : false
> name: Bar instance: FSI_0055+Foos is Bar? : true
> name: Baz instance: FSI_0055+Foos is Bar? : false
*)
答案 3 :(得分:2)
由于歧视联盟可以携带价值观,因此很难看出如果没有实例,这可能会如何发挥作用。
如果你有类似这样的类型:
type Status = Success of string | Error of System.Exception | Timeout
除了你的数组在这种情况下包含成功或错误之外你会怎样?