2014-11-20 49 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) 
} 
相關問題