Scala 在Leon中是否可能对数据结构有要求?
在与leon研究有理数时,我必须在几乎所有地方添加as requirementScala 在Leon中是否可能对数据结构有要求?,scala,leon,Scala,Leon,在与leon研究有理数时,我必须在几乎所有地方添加as requirementisRational 例如: import leon.lang._ case class Rational (n: BigInt, d: BigInt) { def +(that: Rational): Rational = { require(isRational && that.isRational) Rational(n * that.d + that.n * d, d *
isRational
例如:
import leon.lang._
case class Rational (n: BigInt, d: BigInt) {
def +(that: Rational): Rational = {
require(isRational && that.isRational)
Rational(n * that.d + that.n * d, d * that.d)
} ensuring { _.isRational }
def *(that: Rational): Rational = {
require(isRational && that.isRational)
Rational(n * that.n, d * that.d)
} ensuring { _.isRational }
// ...
def isRational = !(d == 0)
def nonZero = n != 0
}
是否可以在类构造函数中添加一个require
语句来干燥此代码,以便它应用于数据结构的所有实例?我试着把它添加到班级的第一行,但似乎没有效果
case class Rational (n: BigInt, d: BigInt) {
require(isRational) // NEW
// ... as before ...
def lemma(other: Rational): Rational = {
Rational(n * other.d + other.n * d, d * other.d)
}.ensuring{_.isRational}
def lemmb(other: Rational): Boolean = {
require(other.d * other.n >= 0)
this <= (other + this)
}.holds
}
(此
和其他
并不总是满足构造函数的要求。)
我遗漏了什么吗?使用不变量的主要困难可以分解为两个问题: 问题1 给定 Leon必须将此要求注入所有函数的前提条件中,以
A
作为参数,因此
def foo(a: A) = {
a.v
} ensuring { _ > 0 }
需要成为:
def foo(a: A) = {
require(a.v > 0)
a.v
} ensuring { _ > 0 }
此情况下,请考虑以下函数:
def foo2(as: List[A]) = {
require(as.nonEmpty)
a.head.v
} ensuring { _ > 0 }
或
在这里,约束foo2
使列表只包含有效的A
s并不容易。Leon必须在ADT上合成遍历函数,以便注入这些先决条件
此外,无法指定集合[A]
只包含有效的A
s,因为Leon缺乏遍历和约束集合的能力
问题2
虽然编写以下函数是可行的:
case class A(a: BigInt) {
require(invariant)
def invariant: Boolean = // ...
}
您有一个鸡和蛋的问题,其中invariant
将被注入一个先决条件检查invariant
我相信这两个问题都可以解决(或者我们可以限制这些不变量的使用),但是它们构成了为什么类不变量还没有被简单地实现的原因。你确定它不起作用吗?我用require测试了你的代码,当我这样做的时候:
Rational(0,0)
它产生:原因:java.lang.IllegalArgumentException:requirement在scala.Predef$.require失败了。test.Rational.(require.scala:207)(require.scala:5)
@AkosKrivachy你的评论让我意识到我问的不是很清楚。我不是说执行代码,而是用Leon验证代码是否正确。我在我的问题中添加了一些具体的例子,如果没有多余的需求陈述,就无法验证。啊,对不起,Leon部分被掩盖了。很抱歉,这帮不了什么忙,但您的问题更详细,所以其他人应该更容易理解。
def foo2(as: List[A]) = {
require(as.nonEmpty)
a.head.v
} ensuring { _ > 0 }
def foo3(as: Set[A], a: A) = {
as contains a
} ensuring { _ > 0 }
case class A(a: BigInt) {
require(invariant)
def invariant: Boolean = // ...
}