ScalaCheck无法将布尔值转换为Prop实例

ScalaCheck无法将布尔值转换为Prop实例

本文介绍了ScalaCheck无法将布尔值转换为Prop实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下属性:

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.P​​rop没有可用的隐式视图.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.P​​rop,隐式a1:org.scalacheck.Arbitrary [List [Int]],隐式s1:org.scalacheck.Shrink [List [Int]],隐式pp1:列表[Int] =>org.scalacheck.util.Pretty)org.scalacheck.P​​rop.未指定的值参数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实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 16:05