F#序列和记录

时间:2017-04-29 09:18:02

标签: f# functional-programming

我有两个序列......

type Suit = Spades | Clubs | Hearts | Diamonds
type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King

type Card = { suit: Suit; rank: Rank}

intValueCard = {rank: Rank; value: int} // translates the union into an actual int

只是想知道如何才能在实际的IC中获得卡的排名...到目前为止我已经

let getActualValue (card:Card) =
    value |> translatedValue.Rank

但是对于我的生活,我无法弄清楚如何处理一个序列而getActualValue无法正常工作..

3 个答案:

答案 0 :(得分:5)

我没有看到任何序列。你有套装和等级是有区别的工会,你有卡是一个记录。不确定intValueCard = {rank: Rank; value: int}的含义是什么,而getActualValue指的是未解释的translateValue。排名中的整数值将用于什么?如果您编辑和改进问题,可以获得更好的帮助。

让我们假设您想要排名以计算游戏中的优势。最好创建一个这样的函数。

let weightFromRank rank =
    match rank with
    | Ace -> 1
    | Two -> 2
    ...etc...

您可以使用function关键字来制作此功能的详细版本。

我认为使用枚举不是一个好主意,因为你会错过函数式编程的重要优势。枚举是.NET类型,而不是功能类型。

不同种类的游戏对Ace有不同的权重。有些比赛让Ace的重量为14,比King高出一个。然后,您可以使用不同的功能来计算重量,具体取决于玩什么类型的游戏。

请注意以下建议,因为我不是F#的顶尖专家。一种不同的方法是将权重作为一个单独的字段放在记录或有区别的联合或类似的东西中。我认为这种方法效率较低,因为权重来自排名,因此您实际上会在不需要的地方复制信息,从而使您的代码更难以理解。处理不同类型游戏的不同权重也会效率低下。

答案 1 :(得分:3)

您可以将Rank声明为枚举:

type Rank = 
    | Ace = 1 
    | Two = 2 
    | Three = 3 
....

然后使用int获取基础值:

let getActualValue ({rank = r}) = int r

答案 2 :(得分:1)

如果你想要整数排名与其他排名进行比较,那么你可以只比较受歧视的联合值,因为比较是免费构建的:

Eight < Nine // true
Jack < Six // false

[Seven; Ace; Four; Two] |> List.sort
// [Ace; Two; Four; Seven]

现在,如果确实因某种原因需要整数排名值,您可以使用反射来获取DU案例。只需确保您在顶级模块值内执行此操作,而不是在函数内部执行此操作,以便在程序启动时仅执行一次反射:

open FSharp.Reflection
let ranks =
    FSharpType.GetUnionCases(typeof<Rank>)
    |> Array.map (fun c -> FSharpValue.MakeUnion(c, [||]) :?> Rank)

let getActualValue rank = Array.findIndex ((=) rank) ranks

getActualValue Ace // 0
getActualValue Two // 1
getActualValue King // 12