问题描述
我具有以下属性:
import org.scalacheck.Prop.propBoolean
def elementsAreReversed(list: List[Int], reversed: List[Int]): Boolean =
if (list.isEmpty) true else {
val lastIdx = list.size - 1
list.zipWithIndex.forall { case (element, index) =>
element == reversed(lastIdx - index)
}
}
val propReversed = Prop.forAll { list: List[Int] =>
val reversed = list.reverse
if (list.isEmpty)
list == reversed
else {
val hasSameSize = reversed.size == list.size
val hasAllElements = list.forall(reversed.contains)
// It works until I add a label here:
hasSameSize && hasAllElements && elementsAreReversed(list, reversed)
}
如果添加标签,则会中断:
If a add a label it breaks:
hasSameSize :| " a label which doesn't let the code compile" &&
hasAllElements &&
elementsAreReversed(list, reversed)
编译器给我以下内容:
错误:(47,36)从Any => org.scalacheck.Prop没有可用的隐式视图.val propReversed = Prop.forAll {list:List [Int] =>
Error:(47, 36) No implicit view available from Any => org.scalacheck.Prop.val propReversed = Prop.forAll { list: List[Int] =>
错误:(47,36)方法forAll的参数不足:
Error:(47, 36) not enough arguments for method forAll:
(隐式p:任意=> org.scalacheck.Prop,隐式a1:org.scalacheck.Arbitrary [List [Int]],隐式s1:org.scalacheck.Shrink [List [Int]],隐式pp1:列表[Int] =>org.scalacheck.util.Pretty)org.scalacheck.Prop.未指定的值参数p,a1,s1 ...
(implicit p: Any => org.scalacheck.Prop, implicit a1: org.scalacheck.Arbitrary[List[Int]], implicit s1: org.scalacheck.Shrink[List[Int]], implicit pp1: List[Int] =>org.scalacheck.util.Pretty) org.scalacheck.Prop. Unspecified value parametersp, a1, s1...
val propReversed = Prop.forAll {list:List [Int] =>
val propReversed = Prop.forAll { list: List[Int] =>
我正在使用ScalaCheck版本1.13.4
I'm using ScalaCheck version 1.13.4
推荐答案
问题是您有一个if
表达式,其真实面为Boolean
类型,而错误面为Prop
类型.如果期望Prop
,则编译器会将propBoolean
隐式转换应用于布尔值,但是这样的条件不是这些条件之一-而是,编译器仅采用Boolean
的最小上限和Prop
并使其成为返回类型. (也许更令人惊讶的是,即使Prop
首先出现,Boolean
第二出现,也是这样.)
The problem is that you've got an if
expression with the true side having type Boolean
and the false side having type Prop
. The compiler will apply the propBoolean
implicit conversion to a boolean value in cases where it expects a Prop
, but a conditional like this isn't one of those places—instead the compiler simply takes the least upper bound of Boolean
and Prop
and makes that the return type. (Maybe a little more surprisingly, this is true even if the Prop
comes first and the Boolean
second.)
有几种方法可以使这项工作有效,但最简单的方法就是显式地应用转换:
There are several ways you could make this work, but the simplest is just to apply the conversion explicitly:
val propReversed = Prop.forAll { list: List[Int] =>
val reversed = list.reverse
if (list.isEmpty) Prop.propBoolean(list == reversed) else {
val hasSameSize = reversed.size == list.size
val hasAllElements = list.forall(reversed.contains)
hasSameSize :| " a label which doesn't let the code compile" &&
hasAllElements && elementsAreReversed(list, reversed)
}
}
对我来说,这只是花哨的隐式转换支持的DSL失败的另一个例子.我喜欢ScalaCheck并每天使用它,但是当这些技巧一旦开始与Scala的(极其复杂的)语法的其他方面进行交互时,这些技巧就将失效时,我并没有真正看到进行反向翻转以支持更简洁的用法的价值.
For me this is just another example of the frustrations of fancy implicit conversion-supported DSLs. I like ScalaCheck and use it every day, but I don't really see the value in doing backflips to support slightly more concise usage when the tricks are just going to break down once they start interacting with other corners of Scala's (enormously complicated) syntax.
这篇关于ScalaCheck无法将布尔值转换为Prop实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!