I used to use an idiom like the following to generate case classes with ScalaCheck:
GenSomething.map2(GenSomethingElse)(MyClass(_, _))
We recently upgraded ScalaCheck to 1.11, which removed the mapN
methods. I'd really like to be able to avoid having to assign intermediate names to the generators for each field, and the mapN
methods provided the easiest way to do that. Now, the best syntax is:
for {
something <- GenSomething
somethingElse <- GenSomethingElse
} yield MyClass(
something = something,
somethingElse = somethingElse)
That's not so bad (for structures will a small number of constructor arguments), but I'd really like to make it clear that there's nothing special going on here, and I'm just specifying generators for each of the arguments without the reader of the code having to read through to confirm that.
In short, I'd like something akin to applicative syntax. Unfortunately, it's not an option to use scalaz, shapeless, or macros. I realize that that last sentence pretty much makes my question "how can I do X without access to the things that let me do X", but I'm hoping that someone will have a good idea.
Since you are explicitly excluding libraries that are meant to prevent boilerplate, you will have to live with some boilerplate.
You can define gen combiners for each arity, using a similar approach to Gen.resultOf. In fact, you can just use Gen.resultOf, since the only difference to resultOf is that you want explicitly provided
Gen
s instead of implicitly providedArbitrary
s.