Scala 在Leon中是否可能对数据结构有要求?

Scala 在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 *

在与leon研究有理数时,我必须在几乎所有地方添加as requirement
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 = // ...
}