It seems that the Discriminative Union with some static methods can handle whatever you want
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
A call to D6.Roll () will generate a single random movie
> D6.Roll();; val it : D6 = Four
> D6.Roll();; val it : D6 = Six
> D6.Roll();; val it : D6 = Two
> D6.Roll();; val it : D6 = Five
You can create static members and operators that make it easy to put your D6s together
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.One < D6.Two;;
val it : bool = true
let rollGen =
let rnd = Random()
let rec gen() = seq { yield rnd.Next(1,7)
yield! gen() }
gen()
> rollGen;;
val rollGen : seq<int>
D6
let d6Gen = rollGen |> Seq.map D6.Create
> d6Gen;;
val d6Gen : seq<D6>
, , ,
let rollList num = rollGen |> Seq.take num |> List.ofSeq
let d6List num = d6Gen |> Seq.take num |> List.ofSeq ;;
let _20rolls = rollList 20 ;;
> val _20rolls : int list =
[3; 4; 2; 3; 5; 6; 4; 6; 6; 6; 5; 3; 4; 3; 2; 1; 2; 5; 3; 6]*)
let _30d6 = d6List 30 ;;
> val _30d6 : D6 list =
[Two; Six; One; Three; Two; Three; One; One; Six; Six; Four; Four; Three;
Four; One; Five; Three; Four; Four; Four; Three; Two; Six; Four; One; Three;
One; Five; Two; Two]