F# F中骰子滚动的建模#
我正在用F#对骰子滚动进行蒙特卡罗模拟,我用整数表示一个骰子滚动,用整数列表表示一个骰子滚动列表。我希望能够将掷骰子而不是整数作为一种类型来建模。我只使用6边骰子,我想要一个具有别名/同义词类型的某些特征以及有区别的并集或枚举的某些属性的类型 这些是我想在我的字体上看到的F# F中骰子滚动的建模#,f#,F#,我正在用F#对骰子滚动进行蒙特卡罗模拟,我用整数表示一个骰子滚动,用整数列表表示一个骰子滚动列表。我希望能够将掷骰子而不是整数作为一种类型来建模。我只使用6边骰子,我想要一个具有别名/同义词类型的某些特征以及有区别的并集或枚举的某些属性的类型 这些是我想在我的字体上看到的 我希望该类型的行为像一个整数,这样我就可以在列表上进行max/min/sum/fold操作 我希望该类型能够被指定为整数值 我想将类型限制为1-6,这样就不会有0的骰子卷和7的骰子卷 我尝试了上面列出的类型组合,但似乎都有一些
这只是一个简单的例子,我只是为了好玩(不是为了赚钱),但我想看到一个答案,因为我可以想象在更严肃的数据建模中使用它。作为选项之一,您可以创建自己的数字类型,如Tomas Petricek在本文中所述:
看起来,一个带有一些静态方法的有区别的联合体可以处理您想要的一切
open System
type D6 =
| One | Two | Three | Four | Five | Six
member self.Value =
match self with
| One -> 1 | Two -> 2 | Three -> 3
| Four -> 4 | Five -> 5 | Six -> 6
override self.ToString() =
match self with
| One -> "One" | Two -> "Two" | Three -> "Three"
| Four -> "Four" | Five -> "Five" | Six -> "Six"
static member Create (num:int) =
match num with
| 1 -> One | 2 -> Two | 3 -> Three
| 4 -> Four | 5 -> Five | 6 -> Six
| _ -> failwithf "Could not create D6, %d is not in range 1-6" num
static member inline Roll() = Random().Next(1,7) |> D6.Create
调用D6.Roll()将生成单个随机滚动
>D6.Roll();;val it:D6=四个
>D6.Roll();;val it:D6=6
>D6.Roll();;val it:D6=两个
>D6.Roll();;val it:D6=5
您可以创建静态成员和运算符,以便轻松地将D6组合在一起
static member inline Add (a:D6) (b:D6) = a.Value + b.Value
static member inline (+) (a , b ) = D6.Add a b
static member inline Subtract (a:D6) (b:D6) = a.Value - b.Value
static member inline (-) (a , b ) = D6.Subtract a b
和静态成员,使从输入列表轻松创建它们
static member FromList (numls: int list ) =
numls |> List.map D6.Create
通过比较可以得出这种类型的框
D6.One>D6.Two;;
val it:bool=false
D6.1
无限序列可以轻松生成随机输入
let rollGen =
let rnd = Random()
let rec gen() = seq { yield rnd.Next(1,7)
yield! gen() }
gen()
>rollGen;;
val rollGen:seq
可以通过映射来创建一个无限的D6随机序列
let d6Gen = rollGen |> Seq.map D6.Create
>d6Gen;;
val d6Gen:序号
如果您想从随机无限序列中提取可以重用的静态输入值列表,则需要使用以下函数
let rollList num = rollGen |> Seq.take num |> List.ofSeq
let d6List num = d6Gen |> Seq.take num |> List.ofSeq ;;
let_20rolls=rollList 20代码>
>val\u 20rolls:int列表=
[3;4;2;3;5;6;4;6;6;5;3;4;3;2;1;2;5;3;6]*)
let _30d6=d630代码>
>val\u 30d6:D6列表=
[2;6;1;3;2;3;1;1;6;6;4;4;3;
四;一;五;三;四;四;四;三;二;六;四;一;三;
一;五;二;二]
只是好奇:你在“思考”掷骰子吗?:)通常的方法是在不导出构造函数的情况下创建一个类型,然后创建一个函数int->dicerll option
,如果参数超出范围,该函数将不返回任何内容。然后,您可以创建一个函数DiceRoll->int
,以提取值并添加您想要支持的任何运算符。我正在参加MOOC,我正在玩骰子计算规则,这些规则创建有趣的概率分布,但玩家很难推理(而不是简单地掷2个骰子).那看起来真的很有用,我以后再试试