-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generating values which depend on each other fails #79
Comments
The problem here is that the final generator is not the result of a FlatMap. I.e. "n" and "m" are completely independent generators within the struct-generator I thing the correct way would look something like this:
Hope this makes sense |
Thanks, that works indeed. Here is the solution a bit reformatted: genIntPair := func() gopter.Gen {
return gen.IntRange(10, 20).FlatMap(func(v interface{}) gopter.Gen {
k := v.(int)
n := gen.Const(k)
m := gen.IntRange(2*k, 50)
var gen_map = map[string]gopter.Gen{"Fst": n, "Snd": m}
return gen.Struct(
reflect.TypeOf(IntPair{}),
gen_map,
)
},
reflect.TypeOf(int(0)))
} So the trick is that the first generated integer value must be re-introduced as generator by applying If you have more dependencies some syntactic sugar would be nice, but this seems to be difficult in Go. |
Scalacheck works well because of scala's for-comprehention notation, which is a very nice way to write these map/flatMap cascades.
actually expands to something like:
I think you could write it like this in go as well, though you have to be very careful when using external variables in anonymous functions. |
I like your FlatMap -> Map approach. This boils down to genIntPair := func() gopter.Gen {
return gen.IntRange(10, 20).FlatMap(func(v interface{}) gopter.Gen {
k := v.(int)
return gen.IntRange(2*k, 50).Map(func(m int) IntPair {
return IntPair{Fst: k, Snd: m}
})
},
reflect.TypeOf(int(0)))
} This is still baroque, but way more to the point than the first version. I will update my example PR #80 |
Example for using flatmap (as in #79)
I am looking for a way to generate values which depend on each other. In particular, I want to recreate the following simple example from ScalaCheck's User Guide (https://github.com/typelevel/scalacheck/blob/main/doc/UserGuide.md#generators), where two integer are generated, the first in the range of
10..20
, the second has a lower bound which is twice as large as the first value:My impression was that the
gen.FlatMap()
should provide the required functionality (in Scala,<-
is a monadic assignment, implemented byFlatMap
), but I failed to find a way to succeed.I defined a simple struct to generate two values which can be fed into the property:
The generator is a straight translation of the Scala code, first generating an integer and then generating a second via accessing the generated value of the first. Both generators are finally stored in the struct generator:
However, it does not work:
Remark: I set the upper bound to
50
instead of500
. The property must still hold, but the generator has a smaller pool to pick suitable values: setting the upper bound to500
often results in a passing property!The text was updated successfully, but these errors were encountered: