हिल्बर्ट के ईपीएसलॉन के साथ बिल्कुल नहीं जानना है, मैं अधिक मौलिक दृष्टिकोण लेता हूं और उपयोग करने के लिए कार्यों का चयन करने के लिए स्कैला चेक के Arbitrary
और Gen
का उपयोग करता हूं।
सबसे पहले, उन कार्यों के लिए बेस क्लास परिभाषित करें जिन्हें आप उत्पन्न करने जा रहे हैं। आम तौर पर, उन कार्यों को उत्पन्न करना संभव होता है जिनमें अपरिभाषित परिणाम होते हैं (जैसे कि शून्य से विभाजित), इसलिए हम PartialFunction
का उपयोग हमारी बेस क्लास के रूप में करेंगे।
trait Fn[A, B] extends PartialFunction[A, B] {
def isDefinedAt(a: A) = true
}
अब आप कुछ कार्यान्वयन प्रदान कर सकते हैं। toString
ओवरराइड करें ताकि स्कैला चेक के त्रुटि संदेश समझदार हों।
object Identity extends Fn[Int, Int] {
def apply(a: Int) = a
override def toString = "a"
}
object Square extends Fn[Int, Int] {
def apply(a: Int) = a * a
override def toString = "a * a"
}
// etc.
मैं मामले वर्गों का उपयोग द्विआधारी कार्यों से एकल कार्यों उत्पन्न करने के लिए चुन लिया है, निर्माता के लिए अतिरिक्त तर्क गुजर। ऐसा करने का एकमात्र तरीका नहीं है, लेकिन मुझे यह सबसे सरल लगता है।
case class Summation(b: Int) extends Fn[Int, Int] {
def apply(a: Int) = a + b
override def toString = "a + %d".format(b)
}
case class Quotient(b: Int) extends Fn[Int, Int] {
def apply(a: Int) = a/b
override def isDefinedAt(a: Int) = b != 0
override def toString = "a/%d".format(b)
}
// etc.
अब आप Fn[Int, Int]
के एक जनरेटर बनाने के लिए, और परिभाषित है कि निहित Arbitrary[Fn[Int, Int]]
के रूप में की जरूरत है। आप जनरेटर को तब तक जोड़ सकते हैं जब तक कि आप चेहरे में नीले रंग न हों (बहुपद, साधारण लोगों से जटिल कार्यों को लिखना आदि)।
val funcs = for {
b <- arbitrary[Int]
factory <- Gen.oneOf[Int => Fn[Int, Int]](
Summation(_), Difference(_), Product(_), Sum(_), Quotient(_),
InvDifference(_), InvQuotient(_), (_: Int) => Square, (_: Int) => Identity)
} yield factory(b)
implicit def arbFunc: Arbitrary[Fn[Int, Int]] = Arbitrary(funcs)
अब आप अपनी संपत्तियों को परिभाषित कर सकते हैं। अपरिभाषित परिणामों से बचने के लिए intG.isDefinedAt(a)
का उपयोग करें।
property("left identity simple funcs") = forAll { (a: Int, intG: Fn[Int, Int]) =>
intG.isDefinedAt(a) ==> (fCat.compose(fCat.id[Int])(intG)(a) == intG(a))
}
property("right identity simple funcs") = forAll { (a: Int, intG: Fn[Int, Int]) =>
intG.isDefinedAt(a) ==> (fCat.compose(intG)(fCat.id)(a) == intG(a))
}
जबकि मैं क्या दिखाया है केवल समारोह का परीक्षण किया सामान्यीकरण करता, उम्मीद है कि यह आप कैसे उन्नत प्रकार प्रणाली प्रवंचना का उपयोग करने के प्रकार से अधिक सामान्यीकरण करने के लिए पर एक विचार दे देंगे।
मुझे आपके प्रश्न का सटीक उत्तर नहीं पता है, लेकिन यह मुझे स्कालज़ में मोनैड कानूनों के चेक की याद दिलाता है। शायद आप https://github.com/scalaz/scalaz/blob/master/tests/src/test/scala/scalaz/MonadTest.scala –
से प्रेरणा ले सकते हैं शायद http://stackoverflow.com/users/53013/daniel -सी-सोब्राल जवाब जानता है? –
यदि प्रकार मनमाने ढंग से चुना जाता है तो आप इसे हिल्बर्ट के ईपीएसलॉन के माध्यम से सार्वभौमिक मात्रा के रूप में देख सकते हैं। Https://gist.github.com/2659013 देखें। –