Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/Hedgehog/Gen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ module Gen =
let list (range : Range<int>) (g : Gen<'a>) : Gen<List<'a>> =
Random.sized (fun size -> random {
let! k = Random.integral range
let! xs = Random.replicate k (toRandom g)
let! xs =
toRandom g
|> List.replicate k
|> ListRandom.sequence
return Shrink.sequenceList xs
|> Tree.filter (atLeast (Range.lowerBound size range))
})
Expand Down Expand Up @@ -488,7 +491,8 @@ module Gen =
let sampleTree (size : Size) (count : int) (g : Gen<'a>) : List<Tree<'a>> =
let seed = Seed.random ()
toRandom g
|> Random.replicate count
|> List.replicate count
|> ListRandom.sequence
|> Random.run seed size

let sample (size : Size) (count : int) (g : Gen<'a>) : List<'a> =
Expand Down
1 change: 1 addition & 0 deletions src/Hedgehog/Hedgehog.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ https://github.com/hedgehogqa/fsharp-hedgehog/blob/master/doc/index.md
<Compile Include="OptionTree.fs" />
<Compile Include="Range.fs" />
<Compile Include="Random.fs" />
<Compile Include="ListRandom.fs" />
<Compile Include="Shrink.fs" />
<Compile Include="Gen.fs" />
<Compile Include="ListGen.fs" />
Expand Down
4 changes: 2 additions & 2 deletions src/Hedgehog/ListGen.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Hedgehog.ListGen

let traverse (f: 'a -> Gen<'b>) (ma: list<'a>) : Gen<list<'b>> =
let traverse (f: 'a -> Gen<'b>) (list: List<'a>) : Gen<List<'b>> =
let rec loop input output =
match input with
| [] -> output |> List.rev |> Gen.constant
Expand All @@ -9,7 +9,7 @@ let traverse (f: 'a -> Gen<'b>) (ma: list<'a>) : Gen<list<'b>> =
let! b = f a
return! loop input (b :: output)
}
loop ma []
loop list []

let sequence (gens : List<Gen<'a>>) : Gen<List<'a>> =
gens |> traverse id
16 changes: 16 additions & 0 deletions src/Hedgehog/ListRandom.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[<RequireQualifiedAccess>]
module Hedgehog.ListRandom

let traverse (f: 'a -> Random<'b>) (list: List<'a>) : Random<List<'b>> =
let rec loop input output =
match input with
| [] -> output |> List.rev |> Random.constant
| a :: input ->
random {
let! b = f a
return! loop input (b :: output)
}
loop list []

let sequence (randoms : List<Random<'a>>) : Random<List<'a>> =
randoms |> traverse id
35 changes: 13 additions & 22 deletions src/Hedgehog/Random.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,48 @@ type Random<'a> =
| Random of (Seed -> Size -> 'a)

module Random =
let private unsafeRun (seed : Seed) (size : Size) (Random r : Random<'a>) : 'a =
let private unsafeRun (seed: Seed) (size: Size) (Random r: Random<'a>) : 'a =
r seed size

let run (seed : Seed) (size : Size) (r : Random<'a>) : 'a =
let run (seed: Seed) (size: Size) (r: Random<'a>) : 'a =
unsafeRun seed (max 1 size) r

let delay (f : unit -> Random<'a>) : Random<'a> =
let delay (f: unit -> Random<'a>) : Random<'a> =
Random (fun seed size ->
f () |> unsafeRun seed size)

let tryFinally (after : unit -> unit) (r : Random<'a>) : Random<'a> =
let tryFinally (after: unit -> unit) (r: Random<'a>) : Random<'a> =
Random (fun seed size ->
try
unsafeRun seed size r
r |> unsafeRun seed size
finally
after ())

let tryWith (k : exn -> Random<'a>) (r : Random<'a>) : Random<'a> =
let tryWith (f: exn -> Random<'a>) (r: Random<'a>) : Random<'a> =
Random (fun seed size ->
try
unsafeRun seed size r
with
x -> unsafeRun seed size (k x))
r |> unsafeRun seed size
with e ->
e |> f |> unsafeRun seed size)

let constant (x : 'a) : Random<'a> =
Random (fun _ _ -> x)

let map (f : 'a -> 'b) (r : Random<'a>) : Random<'b> =
let map (f: 'a -> 'b) (r: Random<'a>) : Random<'b> =
Random (fun seed size ->
r
|> unsafeRun seed size
|> f)

let bind (k : 'a -> Random<'b>) (r : Random<'a>) : Random<'b> =
let join (r: Random<Random<'a>>) : Random<'a> =
Random (fun seed size ->
let seed1, seed2 = Seed.split seed
r
|> unsafeRun seed1 size
|> k
|> unsafeRun seed2 size)

let replicate (times : int) (r : Random<'a>) : Random<List<'a>> =
Random (fun seed0 size ->
let rec loop seed k acc =
if k <= 0 then
acc
else
let seed1, seed2 = Seed.split seed
let x = unsafeRun seed1 size r
loop seed2 (k - 1) (x :: acc)
loop seed0 times [])
let bind (f: 'a -> Random<'b>) (r: Random<'a>) : Random<'b> =
r |> map f |> join

type Builder internal () =
member __.Return(x : 'a) : Random<'a> =
Expand Down