2

假设我有一个受歧视的工会:

type card = Smithy | Cellar | Chapel

以及将可区分联合映射到某个值的函数:

let initialCardCount = function
  Smithy -> 4
  Cellar -> 6
  Chapel -> 2

我想生成一个包含工会每个成员的成本的地图,例如:

[(Smithy, 4); (Cellar, 6); (Chapel, 2)]

这可能吗?我希望能够做类似的事情:

List.zip (allValues f) (List.map getCost (allValues f)) |> Map.ofList

这个问题很有帮助,但不是我所需要的;我希望能够访问内存中的工会成员,而不仅仅是检查他们的属性。

我想这样做的原因是我可以有一个可区分的联合代表游戏中所有不同类型的牌,以及一个告诉你每张牌在开始时应该有多少张的函数,然后轻松生成初始卡片到计数的映射。有一个更好的方法吗?

4

1 回答 1

5

您可以使用 F# Reflection 获得所有可能的可区分联合案例的列表,但了解 Reflection 的缺点很重要 - 除非小心使用,否则很容易导致设计不佳(可能有更简单和更优雅的功能解决方案)和它的效率也较低(尽管您可能只需要一次获取所有案例的列表)。

以下getAllValues函数获取所有案例 - 它假定没有案例存储任何值(即Smithy of string不起作用!)如果您想将一些参数传递给案例,您需要在的第二个参数中传递装箱值MakeUnion

open Microsoft.FSharp.Reflection

let getAllValues<'T>() : 'T list =
  let cases = FSharpType.GetUnionCases(typeof<'T>)
  [ for c in cases -> unbox (FSharpValue.MakeUnion(c, [| |])) ]

以下是在您的场景中使用该函数的示例:

type card = Smithy | Cellar | Chapel 

let initialCardCount = function 
  | Smithy -> 4 
  | Cellar -> 6 
  | Chapel -> 2 

let values = getAllValues<card>()
List.zip values (List.map initialCardCount values)
于 2012-06-03T11:30:14.833 回答