From 3eb3c7830c605f81d113ff49ac39d9bdac9bbaaa Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <ekneuss@gmail.com> Date: Mon, 1 Jun 2015 13:14:29 +0200 Subject: [PATCH] Define updated+insertAt(i: BigInt, e: T), + lemmas from Ravi --- library/collection/List.scala | 77 ++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/library/collection/List.scala b/library/collection/List.scala index 448aea577..daae8ef42 100644 --- a/library/collection/List.scala +++ b/library/collection/List.scala @@ -30,8 +30,9 @@ sealed abstract class List[T] { case Nil() => that case Cons(x, xs) => Cons(x, xs ++ that) }) ensuring { res => - (res.content == this.content ++ that.content) && - (res.size == this.size + that.size) + (res.content == this.content ++ that.content) && + (res.size == this.size + that.size) && + (that != Nil[T]() || res == this) } def head: T = { @@ -285,6 +286,16 @@ sealed abstract class List[T] { (take(c), drop(c)) } + def updated(i: BigInt, y: T): List[T] = { + require(0 <= i && i < this.size) + this match { + case Cons(x, tail) if i == 0 => + Cons[T](y, tail) + case Cons(x, tail) => + Cons[T](x, tail.updated(i - 1, y)) + } + } + def insertAt(pos: BigInt, l: List[T]): List[T] = (this match { case Nil() => l case Cons(h, t) => @@ -300,6 +311,21 @@ sealed abstract class List[T] { res.content == this.content ++ l.content } + def insertAt(pos: BigInt, e: T): List[T] = (this match { + case Nil() => Cons[T](e, Nil()) + case Cons(h, t) => + if (pos < 0) { + insertAt(size + pos, e) + } else if (pos == BigInt(0)) { + Cons(e, this) + } else { + Cons(h, t.insertAt(pos - 1, e)) + } + }) ensuring { res => + res.size == this.size + 1 && + res.content == this.content ++ Set(e) + } + def replaceAt(pos: BigInt, l: List[T]): List[T] = (this match { case Nil() => l case Cons(h, t) => @@ -607,4 +633,51 @@ object ListSpecs { l.scanRight(z)(f).head == l.foldRight(z)(f) }.holds + // A lemma about `append` and `updated` + def appendUpdate[T](l1: List[T], l2: List[T], i: BigInt, y: T): Boolean = { + require(0 <= i && i < l1.size + l2.size) + // induction scheme + (l1 match { + case Nil() => true + case Cons(x, xs) => if (i == 0) true else appendUpdate[T](xs, l2, i - 1, y) + }) && + // lemma + ((l1 ++ l2).updated(i, y) == ( + if (i < l1.size) + l1.updated(i, y) ++ l2 + else + l1 ++ l2.updated(i - l1.size, y))) + }.holds + + // a lemma about `append`, `take` and `drop` + def appendTakeDrop[T](l1: List[T], l2: List[T], n: BigInt): Boolean = { + //induction scheme + (l1 match { + case Nil() => true + case Cons(x, xs) => if (n <= 0) true else appendTakeDrop[T](xs, l2, n - 1) + }) && + // lemma + ((l1 ++ l2).take(n) == ( + if (n < l1.size) l1.take(n) + else if (n > l1.size) l1 ++ l2.take(n - l1.size) + else l1)) && + ((l1 ++ l2).drop(n) == ( + if (n < l1.size) l1.drop(n) ++ l2 + else if (n > l1.size) l2.drop(n - l1.size) + else l2)) + }.holds + + // A lemma about `append` and `insertAt` + def appendInsert[T](l1: List[T], l2: List[T], i: BigInt, y: T): Boolean = { + require(0 <= i && i <= l1.size + l2.size) + (l1 match { + case Nil() => true + case Cons(x, xs) => if (i == 0) true else appendInsert[T](xs, l2, i - 1, y) + }) && + // lemma + ((l1 ++ l2).insertAt(i, y) == ( + if (i < l1.size) l1.insertAt(i, y) ++ l2 + else l1 ++ l2.insertAt((i - l1.size), y))) + }.holds + } -- GitLab