代码之家  ›  专栏  ›  技术社区  ›  Marcus Vinícius Monteiro

ScalaCheck:生成具有任意类型的任意函数

  •  5
  • Marcus Vinícius Monteiro  · 技术社区  · 6 年前

    我实现了以下功能:

    /**
      * Returns a function h , which is the composition of the functions f and g.
      */
    def compose[A, B, C](g: B => C, f: A => B): A => C = f.andThen(g)
    

    我试着用 ScalaCheck 。我可以生成以下测试,这些测试可以编译并通过:

    import org.scalatest.prop.PropertyChecks
    import org.scalatest.{FlatSpec, Matchers}
    
    class ComposeSpec extends FlatSpec with Matchers with PropertyChecks {
    
      "Compose" should "return a function h , which is the composition of the 
    functions f and g" in {
    
        forAll { (a: Int, g: Int => Int, f: Int => Int) =>
          compose(g, f)(a) should be(g(f(a)))
        }
    
        forAll { (a: String, g: Double => Int, f: String => Double) =>
          compose(g, f)(a) should be(g(f(a)))
        }
      }
    }
    

    但是,正如您所看到的,我使用定义的类型生成任意函数,并且还匹配参数的类型 a 函数输入的类型 f .我想做的是这样的:

    forAll { (a: A, g: B => C, f: A => B) =>
      compose(g, f)(a) should be(g(f(a)))
    }
    

    但我不知道它的语法,也不知道它是否可行。你能帮帮我吗?

    1 回复  |  直到 6 年前
        1
  •  5
  •   Joe K    6 年前

    这个 scalatest website 有什么要说的吗 forAll :

    含蓄的 Arbitrary 发电机和 Shrink 需要提供对象 对于 福尔 方法将每行数据传递给每个参数 类型ScalaCheck提供了许多隐式 任意的 发电机 常见类型,如 Int ,则, String ,则, List[Float] org.scalacheck.Arbitrary 伴生对象。只要你使用类型 ScalaCheck已经为其提供了隐式 任意的 发电机, 你不必担心他们。与相同 收缩 对象,它们是 由ScalaCheck提供 org.scalacheck.Shrink 伴生对象。最 通常,您只需将属性函数传递给 福尔 ,以及 编译器将获取ScalaCheck提供的隐式值。

    很遗憾你不能使用 福尔 检查所有可能的类型,因为没有隐式 任意的 收缩 每种可能类型的对象。似乎很难生成任何类型的任意对象。

    您所能做的最好的事情是:

    def checkComposeForAll[A : Arbitrary : Shrink, B : Arbitrary : Shrink, C : Arbitrary : Shrink]() = {
      forAll { (a: A, g: B => C, f: A => B) =>
        compose(g, f)(a) should be(g(f(a)))
      }
    }
    
    checkComposeForAll[Int, Int, Int]()
    checkComposeForAll[String, String, String]()
    checkComposeForAll[List[Int], Double, Int]()
    // ... etc, check a bunch of types ...