diff --git a/library/collection/List.scala b/library/collection/List.scala
index 404c53c44596938abd9b4f7576b923f6778e86ff..4462aca308c5f1756ab9ff5b9e9f42b8a8cc6c8f 100644
--- a/library/collection/List.scala
+++ b/library/collection/List.scala
@@ -6,6 +6,7 @@ import leon._
 import leon.lang._
 import leon.annotation._
 import leon.math._
+import leon.proof._
 
 @library
 sealed abstract class List[T] {
@@ -373,9 +374,9 @@ sealed abstract class List[T] {
     res.size == this.size
   }
 
-  def isEmpty = this match { 
+  def isEmpty = this match {
     case Nil() => true
-    case _ => false 
+    case _ => false
   }
 
   // Higher-order API
@@ -393,7 +394,7 @@ sealed abstract class List[T] {
     case Nil() => z
     case Cons(h, t) => f(h, t.foldRight(z)(f))
   }
- 
+
   def scanLeft[R](z: R)(f: (R,T) => R): List[R] = { this match {
     case Nil() => z :: Nil()
     case Cons(h,t) => z :: t.scanLeft(f(z,h))(f)
@@ -401,12 +402,12 @@ sealed abstract class List[T] {
 
   def scanRight[R](z: R)(f: (T,R) => R): List[R] = { this match {
     case Nil() => z :: Nil[R]()
-    case Cons(h, t) => 
+    case Cons(h, t) =>
       val rest@Cons(h1,_) = t.scanRight(z)(f)
       f(h, h1) :: rest
   }} ensuring { !_.isEmpty }
 
-  def flatMap[R](f: T => List[R]): List[R] = 
+  def flatMap[R](f: T => List[R]): List[R] =
     ListOps.flatten(this map f)
 
   def filter(p: T => Boolean): List[T] = { this match {
@@ -518,20 +519,23 @@ object ListOps {
     case Cons(_, t) => isSorted(t)
   }
 
-  def sorted(ls: List[BigInt]): List[BigInt] = ls match {
-    case Cons(h, t) => insSort(sorted(t), h)
-    case Nil() => Nil()
-  }
+  def sorted(ls: List[BigInt]): List[BigInt] = { ls match {
+    case Cons(h, t) => sortedIns(sorted(t), h)
+    case Nil() => Nil[BigInt]()
+  }} ensuring { isSorted _ }
 
-  def insSort(ls: List[BigInt], v: BigInt): List[BigInt] = ls match {
-    case Nil() => Cons(v, Nil())
-    case Cons(h, t) =>
-      if (v <= h) {
-        Cons(v, t)
-      } else {
-        Cons(h, insSort(t, v))
-      }
-  }
+  private def sortedIns(ls: List[BigInt], v: BigInt): List[BigInt] = {
+    require(isSorted(ls))
+    ls match {
+      case Nil() => Cons(v, Nil())
+      case Cons(h, t) =>
+        if (v <= h) {
+          Cons(v, t)
+        } else {
+          Cons(h, sortedIns(t, v))
+        }
+    }
+  } ensuring { isSorted _ }
 }
 
 case class Cons[T](h: T, t: List[T]) extends List[T]
@@ -547,20 +551,20 @@ object :: {
 }
 
 
+import ListOps._
+
 @library
 object ListSpecs {
-  def snocIndex[T](l : List[T], t : T, i : BigInt) : Boolean = {
+  def snocIndex[T](l: List[T], t: T, i: BigInt): Boolean = {
     require(0 <= i && i < l.size + 1)
-    // proof:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t)) because
     (l match {
       case Nil() => true
       case Cons(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
-    }) &&
-    // claim:
-    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+    })
   }.holds
 
-  def reverseIndex[T](l : List[T], i : BigInt) : Boolean = {
+  def reverseIndex[T](l: List[T], i: BigInt): Boolean = {
     require(0 <= i && i < l.size)
     (l match {
       case Nil() => true
@@ -569,68 +573,160 @@ object ListSpecs {
     (l.reverse.apply(i) == l.apply(l.size - 1 - i))
   }.holds
 
-  def appendIndex[T](l1 : List[T], l2 : List[T], i : BigInt) : Boolean = {
+  def snocLast[T](l: List[T], x: T): Boolean = {
+    ((l :+ x).last == x) because {
+      l match {
+        case Nil() => true
+        case Cons(y, ys) => {
+          ((y :: ys) :+ x).last   ==| trivial         |
+          (y :: (ys :+ x)).last   ==| trivial         |
+          (ys :+ x).last          ==| snocLast(ys, x) |
+          x
+        }.qed
+      }
+    }
+  }.holds
+
+  def headReverseLast[T](l: List[T]): Boolean = {
+    require (!l.isEmpty)
+    (l.head == l.reverse.last) because {
+      l match {
+        case Cons(x, xs) => {
+          (x :: xs).head           ==| trivial                 |
+          x                        ==| snocLast(xs.reverse, x) |
+          (xs.reverse :+ x).last   ==| trivial                 |
+          (x :: xs).reverse.last
+        }.qed
+      }
+    }
+  }.holds
+
+  def appendIndex[T](l1: List[T], l2: List[T], i: BigInt): Boolean = {
     require(0 <= i && i < l1.size + l2.size)
-    (l1 match {
-      case Nil() => true
-      case Cons(x,xs) => if (i==BigInt(0)) true else appendIndex[T](xs,l2,i-1)
-    }) &&
-    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+    ( (l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)) ) because {
+      l1 match {
+        case Nil() => true
+        case Cons(x,xs) =>
+          (i != BigInt(0)) ==> appendIndex[T](xs, l2, i - 1)
+      }
+    }
   }.holds
 
-  def appendAssoc[T](l1 : List[T], l2 : List[T], l3 : List[T]) : Boolean = {
-    (l1 match {
-      case Nil() => true
-      case Cons(x,xs) => appendAssoc(xs,l2,l3)
-    }) &&
-    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  @induct
+  def appendAssoc[T](l1: List[T], l2: List[T], l3: List[T]): Boolean = {
+    (l1 ++ l2) ++ l3 == l1 ++ (l2 ++ l3)
   }.holds
 
-  def snocIsAppend[T](l : List[T], t : T) : Boolean = {
-    (l match {
-      case Nil() => true
-      case Cons(x,xs) =>  snocIsAppend(xs,t)
-    }) &&
-    ((l :+ t) == l ++ Cons[T](t, Nil()))
+  @induct
+  def rightUnitAppend[T](l1: List[T]): Boolean = {
+    l1 ++ Nil() == l1
   }.holds
 
-  def snocAfterAppend[T](l1 : List[T], l2 : List[T], t : T) : Boolean = {
-    (l1 match {
-      case Nil() => true
-      case Cons(x,xs) =>  snocAfterAppend(xs,l2,t)
-    }) &&
-    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  // This follows immediately from the definition of `++` but we
+  // include it here anyway for completeness.
+  def leftUnitAppend[T](l1: List[T]): Boolean = {
+    Nil() ++ l1 == l1
   }.holds
 
-  def snocReverse[T](l : List[T], t : T) : Boolean = {
-    (l match {
-      case Nil() => true
-      case Cons(x,xs) => snocReverse(xs,t)
-    }) &&
-    ((l :+ t).reverse == Cons(t, l.reverse))
+  def snocIsAppend[T](l: List[T], t: T): Boolean = {
+    ( (l :+ t) == l ++ Cons[T](t, Nil()) ) because {
+      l match {
+        case Nil() => true
+        case Cons(x,xs) => snocIsAppend(xs,t)
+      }
+    }
   }.holds
 
-  def reverseReverse[T](l : List[T]) : Boolean = {
-    (l match {
-      case Nil() => true
-      case Cons(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
-    }) &&
-    (l.reverse.reverse == l)
+  def snocAfterAppend[T](l1: List[T], l2: List[T], t: T): Boolean = {
+    ( (l1 ++ l2) :+ t == l1 ++ (l2 :+ t) ) because {
+      l1 match {
+        case Nil() => true
+        case Cons(x,xs) => snocAfterAppend(xs,l2,t)
+      }
+    }
   }.holds
 
-  //// my hand calculation shows this should work, but it does not seem to be found
-  //def reverseAppend[T](l1 : List[T], l2 : List[T]) : Boolean = {
-  //  (l1 match {
-  //    case Nil() => true
-  //    case Cons(x,xs) => {
-  //      reverseAppend(xs,l2) &&
-  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
-  //      l1.reverse == (xs.reverse :+ x)
-  //    }
-  //  }) &&
-  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
-  //}.holds
+  def snocReverse[T](l: List[T], t: T): Boolean = {
+    ( (l :+ t).reverse == Cons(t, l.reverse) ) because {
+      l match {
+        case Nil() => true
+        case Cons(x,xs) => snocReverse(xs,t)
+      }
+    }
+  }.holds
 
+  def reverseReverse[T](l: List[T]): Boolean = {
+    l.reverse.reverse == l because {
+      l match {
+        case Nil()       => trivial
+        case Cons(x, xs) => {
+          (xs.reverse :+ x).reverse ==| snocReverse[T](xs.reverse, x) |
+          x :: xs.reverse.reverse   ==| reverseReverse[T](xs)         |
+          (x :: xs)
+        }.qed
+      }
+    }
+  }.holds
+
+  def reverseAppend[T](l1: List[T], l2: List[T]): Boolean = {
+    ( (l1 ++ l2).reverse == l2.reverse ++ l1.reverse ) because {
+      l1 match {
+        case Nil() => {
+          (Nil() ++ l2).reverse         ==| trivial                     |
+          l2.reverse                    ==| rightUnitAppend(l2.reverse) |
+          l2.reverse ++ Nil()           ==| trivial                     |
+          l2.reverse ++ Nil().reverse
+        }.qed
+        case Cons(x, xs) => {
+          ((x :: xs) ++ l2).reverse         ==| trivial               |
+          (x :: (xs ++ l2)).reverse         ==| trivial               |
+          (xs ++ l2).reverse :+ x           ==| reverseAppend(xs, l2) |
+          (l2.reverse ++ xs.reverse) :+ x   ==|
+            snocAfterAppend(l2.reverse, xs.reverse, x)                |
+          l2.reverse ++ (xs.reverse :+ x)   ==| trivial               |
+          l2.reverse ++ (x :: xs).reverse
+        }.qed
+      }
+    }
+  }.holds
+
+  def snocFoldRight[A, B](xs: List[A], y: A, z: B, f: (A, B) => B): Boolean = {
+    ( (xs :+ y).foldRight(z)(f) == xs.foldRight(f(y, z))(f) ) because {
+      xs match {
+        case Nil() => true
+        case Cons(x, xs) => snocFoldRight(xs, y, z, f)
+      }
+    }
+  }.holds
+
+  def folds[A, B](xs: List[A], z: B, f: (B, A) => B): Boolean = {
+    val f2 = (x: A, z: B) => f(z, x)
+    ( xs.foldLeft(z)(f) == xs.reverse.foldRight(z)(f2) ) because {
+      xs match {
+        case Nil() => true
+        case Cons(x, xs) => {
+          (x :: xs).foldLeft(z)(f)              ==| trivial               |
+          xs.foldLeft(f(z, x))(f)               ==| folds(xs, f(z, x), f) |
+          xs.reverse.foldRight(f(z, x))(f2)     ==| trivial               |
+          xs.reverse.foldRight(f2(x, z))(f2)    ==|
+            snocFoldRight(xs.reverse, x, z, f2)                           |
+          (xs.reverse :+ x).foldRight(z)(f2)    ==| trivial               |
+          (x :: xs).reverse.foldRight(z)(f2)
+        }.qed
+      }
+    }
+  }.holds
+
+  def scanVsFoldLeft[A, B](l: List[A], z: B, f: (B, A) => B): Boolean = {
+    ( l.scanLeft(z)(f).last == l.foldLeft(z)(f) ) because {
+      l match {
+        case Nil() => true
+        case Cons(x, xs) => scanVsFoldLeft(xs, f(z, x), f)
+      }
+    }
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
   //def associative[T,U](l1: List[T], l2: List[T], f: List[T] => U, op: (U,U) => U) = {
   //  f(l1 ++ l2) == op(f(l1), f(l2))
   //}
@@ -643,27 +739,32 @@ object ListSpecs {
   //  associative[T, Boolean](l1, l2, _.exists(p), _ && _ )
   //}.holds
 
-  //@induct
-  //def folds[T,R](l : List[T], z : R, f : (R,T) => R) = {
-  //  { l match {
-  //    case Nil() => true
-  //    case Cons(h,t) => snocReverse[T](t, h)
-  //  }} &&
-  //  l.foldLeft(z)(f) == l.reverse.foldRight((x:T,y:R) => f(y,x))(z)
-  //}.holds
-  //
-
-  //Can't prove this
-  //@induct
-  //def scanVsFoldLeft[A,B](l : List[A], z: B, f: (B,A) => B): Boolean = {
-  //  l.scanLeft(z)(f).last == l.foldLeft(z)(f)
-  //}.holds
-
   @induct
   def scanVsFoldRight[A,B](l: List[A], z: B, f: (A,B) => B): Boolean = {
     l.scanRight(z)(f).head == l.foldRight(z)(f)
   }.holds
 
+  def appendContent[A](l1: List[A], l2: List[A]) = {
+    l1.content ++ l2.content == (l1 ++ l2).content
+  }.holds
+
+  def flattenPreservesContent[T](ls: List[List[T]]): Boolean = {
+    val f: (List[T], Set[T]) => Set[T] = _.content ++ _
+    ( flatten(ls).content == ls.foldRight(Set[T]())(f) ) because {
+      ls match {
+        case Nil() => true
+        case Cons(h, t) => {
+          flatten(h :: t).content                     ==| trivial                       |
+          (h ++ flatten(t)).content                   ==| appendContent(h, flatten(t))  |
+          h.content ++ flatten(t).content             ==| flattenPreservesContent(t)    |
+          h.content ++ t.foldRight(Set[T]())(f)       ==| trivial                       |
+          f(h, Set[T]()) ++ t.foldRight(Set[T]())(f)  ==| trivial                       |
+          (h :: t).foldRight(Set[T]())(f)
+        }.qed
+      }
+    }
+  }.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)