2013-04-30 27 views
0

我想如下生成任意列表:Scalacheck任意使用泛型

scala> def validPairs[T] = Arbitrary.arbitrary[List[(T, Option[T])]] suchThat(!_.isEmpty) 
<console>:8: error: could not find implicit value for parameter a: org.scalacheck.Arbitrary[List[(T, Option[T])]] 
    def validPairs[T] = Arbitrary.arbitrary[List[(T, Option[T])]] suchThat(!_.isEmpty) 

任何想法,我做錯了什麼?使用混凝土類型不需要我定義隱式參數。

scala> def validPairsString = Arbitrary.arbitrary[List[(String, Option[String])]] suchThat(!_.isEmpty) 
validPairsString: org.scalacheck.Gen[List[(String, Option[String])]] 

這是使用Scala的2.9.2和scalacheck 1.10.0

在此先感謝。

+0

發現了一個不同的列表上的答案: 高清validPairs [T:任意] = ... (告訴它,你將提供一個(可能是隱含的)的方式來產生T.) – rubanm 2013-04-30 16:27:50

回答

1

我擊中這個問題我自己試圖生成通用屬性,以後可以爲各種具體類型實例化。我發現OP的答案有點難以置信,所以我認爲提供更詳細的答案會很好。我首先慢慢重複OP的回答。然後證明這同樣適用於使用scalacheck編寫屬性。

的關鍵問題是,以下不編譯(我簡化由OP給出的問題):

def validPair[T] = Arbitrary.arbitrary[(T,T)] 

擁有現代化的Scala編譯器,你得到一個不同的錯誤信息:

diverging implicit expansion for type org.scalacheck.Arbitrary[(T, T)] 
starting with method arbTuple2 in trait ArbitraryArities 

(這樣可以幫助那些Google今天遇到這個問題的人)。

這足以通過任意到綁定的類型參數(OP的答案是有點神祕的快速閱讀):

def validPair[T :Arbitrary] = Arbitrary.arbitrary[(T,T)] 

現在同樣的需求,如果要定義通用屬性來實現。下面是一個關於monoids的關聯性公理的例子:

def associative[A :Arbitrary] (m: Monoid[A]) :Prop = 
    forAll ((a1: A, a2: A, a3: A) => m.op(m.op(a1,a2), a3) == m.op(a1,m.op(a2,a3))) 

它產生一個類似的錯誤,沒有A的任意邊界。我希望別人開始用scalacheck編寫他們的第一個通用屬性會覺得這很有用。

1

發現了一個不同的列表上的答案:DEF validPairs [T:任意] = ...(告訴它,你將提供一個(可能是隱含的)的方式來產生T.)