我正在使用反射枚举 F# 中的一些可区分联合中的值(例如,如何在 F# 中枚举可区分联合?)。我想使用从使用反射获得的值来生成不同的记录类型,这些记录类型由我正在枚举的有区别的联合组成,但我不确定如何将类型 UnionCaseInfo 转换为实际的联合案例。有可能进行这样的演员吗?下面的代码正是我想要做的(区分联合中的值不同,变量名也不同)。我知道我可以使用枚举,但我宁愿不使用它们而不是区分联合。
open System
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Reflection
let GetUnionCaseName (x:'a) =
match FSharpValue.GetUnionFields(x, typeof<'a>) with
| case, _ -> case.Name
type shape =
| Square
| Circle
| Triangle
| Other
type color =
| Black
| Red
| Blue
| Green
| White
type coloredShape = { Shape: shape; Color: color }
let shapeCases = FSharpType.GetUnionCases typeof<shape>
let colorCases = FSharpType.GetUnionCases typeof<color>
let boardOfRelevantPossibilities = Microsoft.FSharp.Collections.Array2D.init<coloredShape> 5 3 (fun x y -> {Shape = Other; Color = Black})
let OtherShape = GetUnionCaseName(shape.Other)
let rand = Random()
for shapeCase in shapeCases do
// Is there a way to do the following comparison this without using string comparisons
if not (shapeCase.Name.Equals OtherShape) then
for colorCase in colorCases do
let mutable addedToBoard = false
while not addedToBoard do
let boardRowIndex = rand.Next(0,4)
let boardColumnIndex = rand.Next(0,2)
if boardOfRelevantPossibilities.[boardRowIndex,boardColumnIndex].Shape.Equals shape.Other then
addedToBoard <- true
// I want to utilize colorCase instead of other and shapeCase instead of black
boardOfRelevantPossibilities.[boardRowIndex,boardColumnIndex] <- {Shape = Other; // Shape should be determined by shapeCase instead of Other
Color = White } // Color should be determined by colorCase instead of White
Console.ReadKey() |> ignore
我将我的代码重新分解为以下内容:
open System
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Reflection
let allUnionCases<'T>() =
FSharpType.GetUnionCases(typeof<'T>)
|> Array.map (fun case -> FSharpValue.MakeUnion(case, [||]) :?> 'T)
type shape =
| Square
| Circle
| Triangle
| Other
type color =
| Black
| Red
| Blue
| Green
| White
type coloredShape = { Shape: shape; Color: color }
let shapeCases = FSharpType.GetUnionCases typeof<shape>
let colorCases = FSharpType.GetUnionCases typeof<color>
let numberOfRows = 5
let numberOfColumns = 3
let boardOfRelevantPossibilities = Microsoft.FSharp.Collections.Array2D.init<coloredShape> numberOfRows numberOfColumns (fun x y -> {Shape = Other; Color = Black})
let rand = Random()
for shapeCase in allUnionCases<shape>() do
// No string comparison anymore
if shapeCase <> shape.Other then
for colorCase in allUnionCases<color>() do
let mutable addedToBoard = false
while not addedToBoard do
let boardRowIndex = rand.Next(0,numberOfRows)
let boardColumnIndex = rand.Next(0,numberOfColumns)
if boardOfRelevantPossibilities.[boardRowIndex,boardColumnIndex].Shape.Equals shape.Other then
addedToBoard <- true
// utilizing colorCase and shapeCase to create records to fill array
boardOfRelevantPossibilities.[boardRowIndex,boardColumnIndex] <- {Shape = shapeCase; Color = colorCase }
printfn "%A" boardOfRelevantPossibilities
Console.ReadKey() |> ignore
这种新的重构结合了反射以枚举可区分联合,同时允许我生成由这些可区分联合组成的不同记录类型。我还发现了两个错误,它们在重构代码中得到修复。