2013-04-30 36 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.)