Create random list of size n using 2 enums in F# type Suit = Club = 1 | Diamond = 2 | Spade = 3 | Heart = 4
type Rank = Two = 2 | Three = 3 | Four = 4 | Five = 5 | Six = 6 | Seven = 7 | Eight = 8 | Nine = 9 | Ten = 10 | Jack = 11 | Queen = 12 | King = 13 | Ace = 14
type Card = { Suit:Suit; Rank:Rank }

let RandomHand (size:int) =            
    let rndSuitIndex (rng:System.Random) = rng.Next(1, System.Enum.GetValues(typeof&lt;Suit&gt;).Length + 1)
    let rndRankIndex (rng:System.Random) = rng.Next(1, System.Enum.GetValues(typeof&lt;Rank&gt;).Length + 2)            
    let randomCard (rng:System.Random) = {Suit=enum&lt;Suit&gt;((rndSuitIndex rng));Rank=enum&lt;Rank&gt;((rndRankIndex rng))}
    let cards (rng:System.Random) = List.init&lt;Card&gt; size (fun index -&gt; randomCard rng)
    cards (System.Random())


As a C# programmer I'm trying to get into F#. I'm trying to create a function that returns a random list of cards. This currently works, but I'm sure this can be written MUCH shorter and cleaner.

Especially using the (rng:System.Random) 4 times feels like a stupid thing to do. Any tips?
I second Mark Seemann's remark regarding enums. It makes much more sense to use discriminated unions to describe the entities in your domain.

A randomizing function will never look completely nice and functional, as it uses a side-effect by definition. Nevertheless, I think there isn't much point in passing around the random seed. It can be initialized once in the beginning of your function.

I think things get much clearer when the function randomHand has the call to List.init as its last line, showing that it creates and returns a list. The card generating function could in principle be made into a lambda, but I couldn't squeeze it into less than 7 lines and fslint doesn't like it...

Here's my suggestion:

type Suit = Club | Diamond | Spade | Heart
type Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
type Card = 
  { Suit: Suit 
    Rank: Rank }

let randomHand size =
  let randomSeed = System.Random ()
  let randomCard _ =
    { Suit = match randomSeed.Next(1, 5) with
             | 1 -&gt; Club | 2 -&gt; Diamond | 3 -&gt; Spade | 4 -&gt; Heart
             | _ -&gt; failwith "random value out of bounds"
      Rank = match randomSeed.Next(2, 15) with
             | 2  -&gt; Two   | 3  -&gt; Three | 4  -&gt; Four | 5  -&gt; Five | 6  -&gt; Six
             | 7  -&gt; Seven | 8  -&gt; Eight | 9  -&gt; Nine | 10 -&gt; Ten  | 11 -&gt; Jack
             | 12 -&gt; Queen | 13 -&gt; King  | 14 -&gt; Ace
             | _ -&gt; failwith "random value out of bounds" }
  List.init size randomCard


Since System.Random.Next() is not bound to a range by its type (int), I had to handle the potential case that it might return a value out of bounds.