我试图证明列表中的大小(元素数量)是非负的,但莱昂未能证明它 - 它只是超时。莱昂真的没有能力证明这个属性,还是我错误地使用它?我的出发点是我在文章“莱昂验证系统概述”中读到的一个函数。
import leon.lang._
import leon.annotation._
object ListSize {
sealed abstract class List
case class Cons(head: Int, tail: List) extends List
case object Nil extends List
def size(l: List) : Int = (l match {
case Nil => 0
case Cons(_, t) => 1 + size(t)
}) ensuring(_ >= 0)
}
答案 0 :(得分:6)
Leon的早期版本将Scala的Int
类型视为数学,无界,整数。最新版本将Int
的值视为带符号的32位向量,并且需要使用BigInt
来表示无界整数。
在提供的示例中,Leon超时尝试构建一个大小为Int.MaxValue
的列表,这是一个反例,它将证明后置条件不适用于有界整数。
如果您将size
的返回类型更改为BigInt
,程序会按预期进行验证。
答案 1 :(得分:0)
以前的答案是正确的,但是如果我们希望使用 Int 而不是 BigInt 并且感觉合理列表的大小是非负的,则对我们没有帮助。以下简单的技巧可以解决这个问题并在不锈钢中起作用:
def listLength(l: List[T]): Int = {
l match {
case head :: tl => {
val tlLen = listLength(tl)
if(tlLen < Int.MaxValue) {
tlLen + 1
} else {
0
}
}
case Nil() => 0
}
} ensuring(0 <= _)
例如,参见 https://github.com/epfl-lara/bolts/blob/master/data-structures/seqs/ArrayList.scala 的 Bolts 存储库中的 https://stainless.epfl.ch/