0

Sorry to resort to math-speak in the subject line. I'll unpack it a little. I want to create an FsCheck generator of records where each field is restricted to discrete values. For instance, a shirt size can be expressed as collar and sleeve lengths.

type Shirt = { Collar : float; Sleeve : float; }

But lengths come in a discrete set of sizes.

let collars = [ 14.0; 14.5; 15.0; 15.5; 16.0; 16.5; 17.0; 17.5; 18.0; ]
let sleeves = [ 30.5; 31.5; 32.5; 33.5; 34.5; 35.5; 36.5; 37.5; 38.5]

Documentation clearly shows how to create individual generators for these collar and sleeve sizes. I'd like to be able to combine them into a generator of Shirt records.

This is a simplified example. My goal is to create generators of database records in a handful of tables and combine those generators.

StevePoling
  • 319
  • 1
  • 15

2 Answers2

2

Not that I ever have used FsCheck, but given your definitions, the easiest way would be probably by way of a list sequence expression.

let collarSleeves = 
    [ for collar in collars do
        for sleeve in sleeves ->
            { Collar = collar; Sleeve = sleeve } ]
let chooseFromCollarSleeves = gen { 
    let! i = Gen.choose (0, List.length collarSleeves - 1) 
    return collarSleeves.[i] }
kaefer
  • 5,491
  • 1
  • 15
  • 20
2

I think this would work for you:

open FsCheck

type Shirt = { Collar : float; Sleeve : float; }

let collars = [ 14.0; 14.5; 15.0; 15.5; 16.0; 16.5; 17.0; 17.5; 18.0; ]
let sleeves = [ 30.5; 31.5; 32.5; 33.5; 34.5; 35.5; 36.5; 37.5; 38.5]

let shirtGen =  gen {
    let! collar = Gen.elements collars
    let! sleeve = Gen.elements sleeves
    return { Collar = collar ; Sleeve = sleeve}
}

shirtGen
|> Gen.sample 0 10
|> Seq.iter (printfn "%A")
AMieres
  • 4,944
  • 1
  • 14
  • 19
  • Strangely, all the examples show Gen.sample with two parameters, but it complains bitterly unless i provide only one. Modulo that change--this works. – StevePoling Oct 24 '18 at 16:09