1
module BirthdayLibrary = 
    type Birthday =
        { day   :int
          month :int }

module DataGen = 
    let birthdayGenerator (months:option<list<int>>) = 
        let monthGen = match months with
                       | Some m -> Gen.elements m
                       | None   -> FsCheck.Gen.choose(1,12)
        (fun m d -> { day   = d
                      month = m}:BirthdayLibrary.Birthday)
        <!> monthGen
        <*> FsCheck.Gen.choose(1,28)

    //I want this to have the signature Gen<BirthdayLibrary.Birthday list>
    let oneForEveryMonthGen = 
        [ for m in [1 .. 12] ->
            (fun mo -> birthdayGenerator (Some [mo]))]

Lets say I have something like the above. I have a birthday generator with the return type of Gen<BirthdayLibrary.Birthday>. You can optionally specify the month. What is the best way to go from a Gen<a> to a Gen<a list> WHILE specifying some constraint to item in the list's gen? I can think of ways to get <Gen<a> list>, which I don't think would work for composing a parent object that should contain a <list a> (which is the basis for this example). I can also think of a way to do Gen<Gen<a> list>, which I had composition problems with as well as all values in the list being the same. I saw Gen.arrayOf bit I can't think of how to get it to work with values for each item in the array.

Hohohodown
  • 718
  • 1
  • 8
  • 23
  • I'll add an answer that gives you the signature you want as well as the constraint, but I must confess I don't fully understand what you're getting at with the composition problems. – Kurt Schelfthout Jan 21 '15 at 09:46
  • By composition problems I meant that I was unable to unwrap a Gen list> to use with an object that had a property of type . – Hohohodown Jan 21 '15 at 20:29

1 Answers1

2
module BirthdayLibrary = 
    type Birthday =
        { day   :int
          month :int }

module DataGen = 
    let birthdayGenerator (months:option<list<int>>) = 
        let monthGen = match months with
                       | Some m -> Gen.elements m
                       | None   -> FsCheck.Gen.choose(1,12)
        (fun m d -> { day   = d
                      month = m}:BirthdayLibrary.Birthday)
        <!> monthGen
        <*> FsCheck.Gen.choose(1,28)

    //I want this to have the signature Gen<BirthdayLibrary.Birthday list>
    let oneForEveryMonthGen = 
        [ for m in [1 .. 12] -> birthdayGenerator (Some [m])]
        |> Gen.sequence

let sample = DataGen.oneForEveryMonthGen |> Gen.sample 10 1

gives me:

val sample : BirthdayLibrary.Birthday list list = [[{day = 7; month = 1;}; {day = 15; month = 2;}; {day = 13; month = 3;}; {day = 14; month = 4;}; {day = 28; month = 5;}; {day = 9; month = 6;}; {day = 28; month = 7;}; {day = 15; month = 8;}; {day = 6; month = 9;}; {day = 21; month = 10;}; {day = 12; month = 11;}; {day = 27; month = 12;}]]

Kurt Schelfthout
  • 8,880
  • 1
  • 30
  • 48