Si consideri la seguente definizione di una categoria:di ordine superiore ScalaCheck
trait Category[~>[_, _]] {
def id[A]: A ~> A
def compose[A, B, C](f: A ~> B)(g: B ~> C): A ~> C
}
Ecco un esempio per le funzioni unari:
object Category {
implicit def fCat = new Category[Function1] {
def id[A] = identity
def compose[A, B, C](f: A => B)(g: B => C) = g.compose(f)
}
}
Ora, categorie sono soggetti ad alcune leggi. composizione relativa (.
) e l'identità (id
):
forall f: categoryArrow -> id . f == f . id == f
Voglio testare questo con ScalaCheck. Proviamo per le funzioni sopra interi:
"Categories" should {
import Category._
val intG = { (_ : Int) - 5 }
"left identity" ! check {
forAll { (a: Int) => fCat.compose(fCat.id[Int])(intG)(a) == intG(a) }
}
"right identity" ! check {
forAll { (a: Int) => fCat.compose(intG)(fCat.id)(a) == intG(a) }
}
}
Ma questi sono quantificate sopra (i) un tipo specifico (Int
), e (ii) una specifica funzione (intG
). Quindi, ecco la mia domanda: fino a che punto posso andare in termini di generalizzazione dei test precedenti e come? O, in altre parole, sarebbe possibile creare un generatore di funzioni arbitrarie A => B
e fornire quelle a ScalaCheck?
Non conosco la risposta esatta alla tua domanda, ma mi ricorda i controlli per le leggi della monade in scalaz. Forse puoi trarre ispirazione da https://github.com/scalaz/scalaz/blob/master/tests/src/test/scala/scalaz/MonadTest.scala –
forse http://stackoverflow.com/users/53013/daniel -c-sobral conosce la risposta? –
Se il tipo è scelto arbitrariamente, è possibile visualizzarlo come quantificazione universale tramite epsilon di Hilbert. Vedi https://gist.github.com/2659013. –