2014-11-20 65 views
2

我用类似下面用ScalaCheck生成case类的成语:如何在使用ScalaCheck生成案例类时避免使用样板文件?

GenSomething.map2(GenSomethingElse)(MyClass(_, _)) 

我们最近升级ScalaCheck至1.11,其中除去mapN方法。我真的希望能够避免必须为每个字段的生成器分配中间名,并且方法提供了最简单的方法。现在,最好的语法是:

for { 
    something <- GenSomething 
    somethingElse <- GenSomethingElse 
} yield MyClass(
    something = something, 
    somethingElse = somethingElse) 

这并不是那么糟糕(的结构将构造参数数量少),但我真的很想说清楚,没有什么特别的地方,我只是为每个参数指定生成器,而不需要代码阅读器读者来确认。

总之,我想要类似于应用语法的东西。不幸的是,它不是使用scalaz,无形或宏的选项。我意识到,最后一句话几乎使我的问题是“我怎么能做X而不能访问让我做X的事情”,但我希望有人会有一个好主意。

+0

的可能的复制[scalacheck案例类随机数据发生器(http://stackoverflow.com/questions/33370733/scalacheck-case-class-random-data-generator) – 2015-10-27 16:16:54

+0

这不是一个真正的重复,为有两个原因:1,我明确地不能使用无定形(就像我想要的那样),2,我想指定显式生成器而不是使用任意实例,这是Gen.resultOf无法做到的,这个问题的答案对我有用。 – j3h 2015-11-02 21:29:26

回答

0

由于您明确排除了用于防止样板文件的库,因此您将不得不使用某些样板文件。

您可以使用与Gen.resultOf类似的方法为每个元素定义gen组合器。实际上,您可以使用Gen.resultOf,因为与resultOf唯一的区别在于您希望明确提供Gen而不是隐式提供Arbitrary s。

object GenCombiner { 

    def zipMap[A, R](a: Gen[A])(f: A ⇒ R): Gen[R] = 
    Gen.resultOf(f)(Arbitrary(a)) 

    def zipMap[A, B, R](a: Gen[A], b: Gen[B])(f: (A, B) ⇒ R): Gen[R] = 
    Gen.resultOf(f)(Arbitrary(a), Arbitrary(b)) 

    def zipMap[A, B, C, R](a: Gen[A], b: Gen[B], c: Gen[C])(f: (A, B, C) ⇒ R): Gen[R] = 
    Gen.resultOf(f)(Arbitrary(a), Arbitrary(b), Arbitrary(c)) 

    // other arities 
} 

object GenCombinerTest { 
    import GenCombiner._ 

    case class Foo(alpha: String, num: String) 

    val fooGen: Gen[Foo] = zipMap(Gen.alphaStr, Gen.numStr)(Foo) 
} 
相关问题