forked from epfl-lara/stainless
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ChooseWithWitness.scala
51 lines (41 loc) · 1.21 KB
/
ChooseWithWitness.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/* Copyright 2009-2021 EPFL, Lausanne */
import stainless.annotation._
import stainless.lang._
object ChooseWithWitness {
sealed abstract class List
case class Cons(head: Int, tail: List) extends List
case class Nil() extends List
def size(l: List) : BigInt = (l match {
case Nil() => BigInt(0)
case Cons(_, t) => 1 + size(t)
}).ensuring(res => res >= 0)
def content(l: List) : Set[Int] = l match {
case Nil() => Set.empty[Int]
case Cons(x, xs) => Set(x) ++ content(xs)
}
def createListOfSize(i: BigInt): List = {
require(i >= 0)
if (i == BigInt(0)) {
Nil()
} else {
Cons(0, createListOfSize(i - 1))
}
}.ensuring( size(_) == i )
def listOfSize(i: BigInt): List = {
require(i >= 0)
if (i == BigInt(0)) {
Nil()
} else {
assert(size(createListOfSize(i)) == i) // provides choose quantification with a matcher
choose[List] { (res: List) => size(res) == i }
}
}.ensuring( size(_) == i )
def listOfSize2(i: BigInt): List = {
require(i >= 0)
if (i > 0) {
Cons(0, listOfSize(i-1))
} else {
Nil()
}
}.ensuring( size(_) == i )
}