Dafny makes use of a decreases clause to verify that a recursive function terminates. When verification fails can Dafny be given a hint, in this case in the form of a lemma. How to I tell Dafny to use the lemma when checking that the decreases clause actually decreases?
datatype List<T> = Nil | Cons(head:T, tail:List<T>)
datatype Twee = Node(value : int, left : Twee, right : Twee) | Leaf
function rotateLeft(t:Twee) :Twee
{
match t
case Leaf => t
case Node(v,Node(vl,ll,rl),r) => Node(vl,ll,Node(v,rl,r))
case Node(v,Leaf,r) => Node(v,Leaf,r)
}
function Leftheight(t:Twee) :(h:nat) decreases t
{
match t
case Leaf => 0
case Node(_,l,_) => 1+Leftheight(l)
}
lemma {:induction ll, rl, r} decreasesHint(v:int, vl:int, ll:Twee,rl:Twee,r:Twee)
ensures Leftheight(Node(v,Node(vl,ll,rl),r)) ==
1+ Leftheight(Node(vl,ll, Node(v,rl,r))) {}
function rotateAllLeft(t:Twee) :Twee
decreases t, Leftheight(t)
{
match t
case Leaf => Leaf
case Node(v,Leaf,r) => Node(v,Leaf,rotateAllLeft(r)) //decrases t
case Node(v,Node(vl,ll,rl),r) => //{ decreasesHint(v,vl,ll,rl,r);}
rotateAllLeft(rotateLeft(Node(v,Node(vl,ll,rl),r)))
}
Sorry for such a long example but this is the first time I have wanted to give hints for checking termination. The error failure to decrease termination measure
occurs on the last line rotateAllLeft(rotateLeft(Node(v,Node(vl,ll,rl),r)
.