Modeling cubes in F #

I do some Monte Carlo simulations on rolls with dice using F #, and I use integers to represent one roll of dice and a list of integers to represent the list of dice rolls. I would like to be able to simulate a roll of bone instead of integers as a type. I use only 6-sided dice, and I need a type that has some characteristics like Alias ​​/ Synonym and some properties of either the Discrimination Union or Enum.

This is what I would like to see in my type

  • I would like the type to behave as an integer, so I can max / min / sum / fold in lists.
  • I would like the type to be assigned as an integer value.
  • I would like the type to be limited to 1-6, so there cannot be a single roll of a die of zero and not a single roll of a cube of seven.

I tried a combination of the types listed above, and everyone seems to have some back spins (this could be my use and understanding, and not the types themselves).

This is just a trivial example of what I am doing for pleasure (and not for profit), but I would like to see the answer, as I could imagine, using this for more serious data modeling.

+4
source share
2 answers

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]

+3

All Articles