ScalaCheck: генерировать произвольные функции с произвольными типами - PullRequest
0 голосов
/ 18 мая 2018

Я реализовал следующую функцию:

/**
  * 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 Ответ

0 голосов
/ 18 мая 2018

Самый масштабный веб-сайт может сказать о forAll:

Неявный генератор Arbitrary и объект Shrink должны быть предоставлены для forAllМетод передает каждую строку данных каждому типу параметра.ScalaCheck предоставляет множество неявных генераторов Arbitrary для распространенных типов, таких как Int, String, List[Float] и т. Д., В своем сопутствующем объекте org.scalacheck.Arbitrary.Пока вы используете типы, для которых ScalaCheck уже предоставляет неявные генераторы Arbitrary, вам не нужно беспокоиться о них.То же самое для Shrink объектов, которые предоставляются сопутствующим объектом ScalaCheck org.scalacheck.Shrink.Чаще всего вы можете просто передать функцию свойства в forAll, и компилятор получит неявные значения, предоставляемые ScalaCheck.

Так что, к сожалению, вы не можете использовать forAll для проверки всех возможных типовпотому что не существует неявных Arbitrary и Shrink объектов для каждого возможного типа.Кажется довольно невозможным генерировать произвольные объекты любого типа.

Лучшее, что вы могли бы сделать, это что-то вроде:

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 ...
...