// ------------------ generic list, non-generic tree datatype List { Nil; Cons(T, List); } datatype Tree { Node(int, List); } static function Inc(t: Tree): Tree { match t case Node(n, children) => #Tree.Node(n+1, ForestInc(children)) } static function ForestInc(forest: List): List { match forest case Nil => forest case Cons(tree, tail) => #List.Cons(Inc(tree), ForestInc(tail)) } // ------------------ generic list, generic tree (but GInc defined only for GTree datatype GTree { Node(T, List>); } static function GInc(t: GTree): GTree { match t case Node(n, children) => #GTree.Node(n+1, GForestInc(children)) } static function GForestInc(forest: List>): List> { match forest case Nil => forest case Cons(tree, tail) => #List.Cons(GInc(tree), GForestInc(tail)) } // ------------------ non-generic structures datatype TreeList { Nil; Cons(OneTree, TreeList); } datatype OneTree { Node(int, TreeList); } static function XInc(t: OneTree): OneTree { match t case Node(n, children) => #OneTree.Node(n+1, XForestInc(children)) } static function XForestInc(forest: TreeList): TreeList { match forest case Nil => forest case Cons(tree, tail) => #TreeList.Cons(XInc(tree), XForestInc(tail)) } // ------------------ fun with recursive functions function len(l: List): int { match l case Nil => 0 case Cons(h,t) => 1 + len(t) } function SingletonList(h: T): List ensures len(SingletonList(h)) == 1; { #List.Cons(h, #List.Nil) } function Append(a: List, b: List): List ensures len(Append(a,b)) == len(a) + len(b); { match a case Nil => b case Cons(h,t) => #List.Cons(h, Append(t, b)) } function Rotate(n: int, l: List): List requires 0 <= n; ensures len(Rotate(n, l)) == len(l); { match l case Nil => l case Cons(h, t) => if n == 0 then l else Rotate(n-1, Append(t, SingletonList(h))) }