[Agda] Re: [Coq-Club] Re: Agda beats Coq (was: Termination proof in partiality monad)

Dan Doel dan.doel at gmail.com
Mon Nov 24 13:42:03 CET 2008


On Saturday 22 November 2008 10:25:51 pm Dan Doel wrote:
> And, I think that the coinductive syntax is misleading on this front, when
> you see:
>
>   j ~ cosuc i
>
> You may think, "j is built from an i and a cosuc constructor", but *this is
> not the case*.

I was thinking about the codata situation a bit earlier, and had sort of a 
flash of insight (which after looking up older posts on the subject, I realized 
was something that had been said before, but I hadn't fully understood yet) 
that this is probably the key difference between the codata in Agda/Coq, and 
Anton Setzer's coalgebra formulation, and may be the key thing that codata 
gets "wrong." In fact, the codata approach not only leads one to believe that 
a coinductive value is built from constructors, it treats things as if that 
were the case!

In long, a couple of the problems with codata are that 'evaluation doesn't 
preserve types' and 'it seems that if we just evaluate some of the terms more, 
we could show that one is equal to the other, but equating two values in this 
way is undecidable in general.' But, both of these assume that coinductive 
values are subject to evaluation in the first place, and that said evaluation 
leaves you with some nested constructors as with inductive values! However, if 
my understanding of Setzer's coalgebra formulation is correct, it is not 
correct to say that values with coinductive type are subject to any reduction 
at all (or at least, it shouldn't be, I think). Only observation is.

Perhaps the best illustration is:

  out : Conat -> Conat
  out cozero    = cozero
  out (cosuc n) = cosuc n

This is the type of function people use in Coq and Agda to force evaluation 
when they desire it for proofs and whatnot. However, consider if we look at 
something like the coalgebra approach:

  coalgebra Conat : Set where
    _* : Conat -> 1 + Conat

  -- these are the equivalents of cozero and cosuc used as 'constructors'
  -- on the right hand side of an equation (or in an indexed family definition
  -- for that matter).
  cozero : Conat
  cozero * = inl ()

  cosuc : Conat -> Conat
  (cosuc n) * = inr n

  anaConat : {a : Set} -> (a -> 1 + a) -> a -> Conat
  anaCona f a = bimap id (anaConat f) (f a)

We may ask what the equivalent of out is. There are two possibilities:

  out1 : Conat -> 1 + Conat
  out1 n = n *

  out2 : Conat -> Conat
  (out2 n) * = n *

However, neither of these perform the same function as out. In the first case, 
we cannot even begin to ask if 'out1 c == c' because they don't even have the 
same type (or if we have a heterogeneous equality, the answer is simply "no")! 
On the other hand, we can ask if 'out2 c == c', since they have the same type, 
but, if c is not subject to evaluation, then neither is 'out2 c', so we simply 
compare the terms directly, notice they aren't identical, and the answer is 
"no" (again).

So, the fact that we can prove that "out c == c" under codata, because we can 
evaluate coinductive values and compare the 'constructors' and constituent 
terms we get from doing so seems to be the anomaly. So, I think, tentatively, 
that it should be the case that 'out c /= c'. This, of course, makes 
intensional equality pretty worthless, but perhaps that's the way it should 
be, as equality for coinductive types is rather inherently extensional, and it 
isn't difficult to produce coinductive values that are equal but not 
(instensionally) provably so anyhow:

  i : Conat
  i = anaConat inl 5

  j : Conat
  j = anaConat inl "a string"

  w : Conat
  w * = inl w

All of these are extensionally equal, but you'll never be able to unfold them 
to a point where they match each other; their equality can only be shown by 
proving they are bisimulations of one another.

(I realize this is significantly less onerous than 'out c /= c', but I'd 
tentatively suggest coinductive types are already even worse about intensional 
equality than functions are; functions are similar to coinductive types, 
inasmuch as many are infinite (set/list of input-output pairs), and their 
equality is specified in terms of the observations you can make of them 
(application to values), but we have rules for reducing lambda terms to others 
that denote equivalent functions, whereas there are no such rules (that I know 
of) for coinductive types in general.)

Of course, making intensional equality worthless for coinductive types may 
make them too cumbersome to work with, and may not be the right choice for Coq 
or Agda (at the moment at least). But, I think this may be the root of the 
problem with the codata approach.

As I said, this insight isn't particularly new (although I was pleased to have 
come up with it on my own :)), but it hadn't been mentioned in this thread 
yet.

Cheers,
-- Dan


More information about the Agda mailing list