POSTUlATE_TERMINATION --- Was: Re: [Agda] termination by contradiction

Dominique Devriese dominique.devriese at cs.kuleuven.be
Thu Jul 17 14:25:37 CEST 2014


Wolfram,

2014-07-14 11:54 GMT+02:00 Wolfram Kahl <kahl at cas.mcmaster.ca>:
> On Fri, Jul 04, 2014 at 08:12:44PM +0200, Ulf Norell wrote:
>> The --no-termination-check flag will still treat functions as terminating.
>> The motivation for the
>> new behaviour (which I honestly thought was the intended behaviour all
>> along) is to let you
>> write possibly non-terminating programs without jeopardising decidability
>> of type checking.
>
> Perhaps a POSTULATE_TERMINATION pragma might be useful;
> with the intention that this would be used for terminating functions
> that the (current) termination checker does not recognise as such.
> The type checker would trust this just like a postulate;
> this of course means that if the function in question does in fact
> not terminate, the type checker will loop.
> Just like with postulates, *.agdai files should then also be generated.
> Theoretically, the definition could be considered as given via
> Induction.* with postulates for the relevant wellfoundedness properties.
> (``safe'' mode should of course reject it.)

As Andreas said: NO_TERMINATION_CHECK might be what you are asking
for.  I just want to point out though (for clarity of discussion) that
your comparison with postulates might be a bit misleading. The point
is that adding a postulate to Agda will never make the type-checker
loop, even if you use a postulate of False in the termination proof of
another function (say "f") through Induction.*.  Instead, the
typechecker will block on the application of the postulate and the
function "f" will not reduce. The NO_TERMINATION_CHECK approach does
have the potential to make the type-checker loop. On the flip side:
postulates may make you lose canonicity, while the
NO_TERMINATION_CHECK approach doesn't if you only use it for functions
that do actually terminate.

For a more concrete explanation, consider the following:

  open import Induction.Nat

  postulate x<x : forall {x : Nat} -> x < x

  f : (n : Nat) -> Something
  f = <-rec go
    where go : (n : Nat) -> (indHyp : k -> k < n -> Something) -> Something
              go n indHyp = indHyp n x<x

The point is that normalising "f 3" will not make the type-checker
loop.  Instead, it will reduce to something like "go 3 (... (x < x))"
which will block because x<x doesn't reduce.

On the other hand, if you write the equivalent with NO_TERMINATION_CHECK:

  {-# NO_TERMINATION_CHECK #-}
  f : (n : Nat) -> Something
  f n = f n

Then normalising "f 3" *will* make the type-checker loop.

Regards,
Dominique


More information about the Agda mailing list