如何在代码

时间:2015-05-11 20:29:24

标签: f# functional-programming immutability poker

假设我试图在f#中实现某种扑克计划。首先是这种类型系统的正确使用,这里有大量的新手。

type Suit =
    | Hearts
    | Diamonds
    | Spades
    | Clubs

type Card = {
    Suit:Suit
    Rank:int
}

type Hand = {
    Cards:List<Card>
}

无论如何,假设我想要一个函数来返回一个可能的持卡的随机列表。我想有两个函数可以链接在一起,但是我很难实现它们而不会产生大量的对象。列表模块中的每个函数都将返回一个新列表,而let关键字无法更改引用的值。那么实现这一目标的功能方式是什么。到目前为止我有这个

let generateCards = {
    let ranks = [ 1..52 ]...

} 

let shuffle cards = {

}

let cards = shuffle generateCards

1 个答案:

答案 0 :(得分:4)

一种改组牌组的方法是用一系列随机数字拉链,然后按这些数字排序,然后再解压缩。

let allCards = 
  [ for rank in 2..14 do
      for suit in [Hearts; Diamonds; Spades; Clubs] do
        yield { Suit = suit; Rank = rank } ]

let shuffle cards = 
    let rnd = System.Random()
    let rndSequence = Seq.initInfinite (fun _ -> rnd.Next())
    Seq.zip cards rndSequence |> Seq.sortBy snd |> Seq.map fst |> Seq.toList

shuffle allCards

上面的内容也可以简化(对@ DaveShaw的评论点头),但是以人们不太明显为代价,通过随机生成的密钥对序列进行排序:

let shuffle cards = 
    let rnd = System.Random()
    cards |> List.sortBy (fun _ -> rnd.Next())

甚至更简单(但可能会产生更多性能影响):

let shuffle cards = List.sortBy (fun _ -> System.Guid.NewGuid()) cards

为了极致简洁,请采用无点风格:

let shuffle = List.sortBy (fun _ -> System.Guid.NewGuid())