I cannot seem to figure out why the following fails to establish termination;
datatype Expr = Const(nat) | Add(Expr,Expr)
function eval(e: Expr) : nat
decreases e {
match e
case Const(v) => v
case Add(e1,e2) => evalAdd(e1,e2)
}
function evalAdd(e1: Expr, e2: Expr) : nat
decreases e1,e2 {
var n1 := eval(e1);
var n2 := eval(e2);
n1 + n2
}
I am aware that there are several ways I could prove termination here:
- Inlining
evalAdd()
intoeval()
solves the problem. However, this is part of a larger example where I want to split out functionality rather than have a single largematch
statement. - Defining a notion of
height(Expr)
also solves the problem. However, to my mind, this should not be necessary.
Thoughts?