One option would be to write your predicate without any ensures initially, write a lemma ensuring its properties, and then write a wrapper around the original predicate. It can provide ensures about the original predicate without running into termination errors, and it can call the lemma to make proving those properties easier.
Another option, which might be more what you're looking for, is to use Dafny's support for higher-order functions. For example, you could write something like this:
Hope this helps.
Another option, which might be more what you're looking for, is to use Dafny's support for higher-order functions. For example, you could write something like this:
method Test(ghost R:(int,int)->bool)
requires forall x, y :: R.requires(x,y);
requires forall x, y :: x == y ==> R(x, y);
requires forall x, y, z :: R(x, y) && R(y, z) ==> R(x, z);
requires forall x, y :: R(x, y) || R(y, x);
predicate Leq(x:int, y:int)
{
x <= y
}
method Main()
{
Test(Leq);
}
If you want to talk about lots of relations that have those properties, you could abstract the requires on Test into a predicate of its own.Hope this helps.