[Agda] Codata oddity
Anton Setzer
A.G.Setzer at swansea.ac.uk
Sat Jun 7 03:06:03 CEST 2008
Nils Anders Danielsson wrote:
> Hi,
>
> The current implementation of codata seems to be a bit problematic.
> The following program was suggested by Nicolas Oury:
>
> data _≡_ {a : Set} (x : a) : a -> Set where
> refl : x ≡ x
>
> codata Stream : Set where
> cons : Stream -> Stream
>
> out : Stream -> Stream
> out (cons xs) = cons xs
>
> out-≡ : (xs : Stream) -> xs ≡ out xs
> out-≡ (cons xs) = refl
>
> ω : Stream
> ω ~ cons ω
>
> p : ω ≡ cons ω
> p = out-≡ ω
>
> If we evaluate p we get refl, but if we replace the right-hand side of
> p with refl we get a type error, so we do not have preservation of
> types.
>
>
> ------------------------------------------------------------------------
>
>
I like very much that coalgebras have been added to Agda and I think that's
a necessary step to take. And I think that many things work out nicely
is a real success story.
However, I am worried that we might soon regret such fast success and
the above example demonstrates what happens if one is not 100% clear
about what one is doing.
In my opinion it is important to keep here a clear connection with
category theory and then define some nice abbreviations so that we can
write
code which is as close as possible to equations we want to have (such as
omega = S omega)
without breaking the connection to a clean category theoretic formulation.
In category theory, data is a construct which corresponds to initial
algebras.
E.g. the natural numbers correspond to the initial algebra
intro : 1 + N -> N
where
intro inl = 0
intro (inr n) = S n
or in general
intro : F(X) -> X for some strictly positive functor F
The dual of an initial algebra is a final coalgebra, which is given by
elim : X -> F(X)
In order to obtain decidable type checking one needs to replace final
algebra by weakly final coalgebras, which essentially corresponds
to allowing functions to be defined by guarded recursion,
but there might be several functions satisfying the same guarded
recursion equation.
Following this category theoretic definition, the co-natural numbers
should be defined then as
coalg coNat : Set where
case : coNat -> Z + S (n : coNat)
where Z + S(n : coNat) is the same as
data constrCoNat : Set where
Z : constrCoNat
S : coNat -> S constrCoNat
Note that this means in particular that
neither Z nor S n are elements of coNat
We can define the element corresponding to zero and successor
in coNat by guarded recursion, namely
Z' : coNat where
case Z' = Z
S' : coNat -> coNat where
case (S' n) = S n
This doesn't look nice compared with defining something
like codata, but there is a difference between S' n and S n
When using codata one tries to identify S' n and S n and omit the case
construct
by a new symbol ~, and suddenly we get a confusion,
because it is not clear when to unfold a guarded recursion
and when not.
If we keep the distinction we see that if we rewrite the above example
slighly as
omega : coNat where
case omega = S omega
data Eq (n : coNat) : coNat -> Set where
refl : Eq n n
p : Eq omega (S omega)
p = ?
that Eq omega (S omega) doesn't make any sense.
We can insteadn try
p : Eq omega (S' omega)
p = ?
but now omega and (S' omega) are irreducible elements
(since case is not applied to either of them).
I don't think we will get any clear concepts in Agda by hacking around
this problem.
What we can do is to define good notations and good syntactic sugar
so that we can use something which looks very close to
codata, but which actually is nothing but a good notation for
the real notions coming from category theory, namely coalgebras.
What we came up during the Nottingham dependently typed workshop
in discussions with Ulf and Nils was that a solution for getting good
syntactic
sugar is to have the following:
codata coNat : Set where
Z : coNat
S : coNat -> coNat
is syntactic sugar for the following:
coalg coNat : Set where
-* : coNat -> Z' + S' (n : coNat)
Z : coNat
Z * = Z'
S : coNat -> coNat
(S n) * = S' n
and we have the abbreviation
a ~ b stands for a * = b *
Then we can essentially hide Z', S' n
and write Z' *, (S n) * for them and then write guarded recursion
equations like
omega : coNat
omega ~ S omega
If we take into account that all of this is just syntactic
sugar (not a hack) which translates back into
coalgebras above, then we can answer questions like
Does
p: Id omega (S omega)
p = refl
make sense?
It doesn't, because (S omega) and omega are elements
which don't reduce unless we apply _* to them
(which looks with this notation as if we have to apply them to *)
However, I think even if we have this nice syntactic sugar,
I think notions like coalg need to be kept,
since when evaluating terms we will most likely end up with
raw terms which are elements of some coalg type.
And it is nice to explain what the syntactic sugar actually means.
What about pattern matching?
It looks nice to have something like
f : coNat -> Bool
f Z = tt
f (S n) = ff
But this suggest that if n: coNat then
n = Z or n = S n'
which is not true.
All we have is that
n ~ Z or n ~ S n'
If you do anything else, users will get confused because
then they get the impression that omega = S omega
which is not the case.
The best notation I could find at present is to say we have
f : coNat -> Bool
f n with~ n
.. | Z = tt
.. | S n' = ff
as an abbreviation for
f : coNat -> Bool
f n with n *
.. | Z * = tt
.. | (S n') * = ff
which is the right thing since for every n we have
n ~ Z or n ~ S n'
This is not so nice if we want to have deeper pattern matching like
f : coNat -> Bool
f n with~ n
.. | Z = tt
.. | (S n') with~ n'
.. | Z = tt
.. | (S n') = ff
but I don't see yet a way to avoid this,
since for n : coNat we don't have
n ~ Z or n ~ (S Z) or n ~ S (S n') for some n'.
All we have is
n ~ Z or n ~ (S n') where
n' ~ Z or n' ~ (S n'') for some n''
This is an attempt to get syntactic sugar which is as close
to the codata construct.
But I think we should make sure that whatever we define
clearly corresponds to the categorical constructs, otherwise
we will sooner or later get a lot of confusion.
Anton
--
---------------------------------------
Anton Setzer
Department of Computer Science
Swansea University
Singleton Park
Swansea SA2 8PP
UK
Telephone:
(national) (01792) 513368
(international) +44 1792 513368
Fax:
(national) (01792) 295708
(international) +44 1792 295708
Visiting address:
Faraday Building,
Computer Science Dept.
2nd floor, room 211.
Email: a.g.setzer at swan.ac.uk
WWW:
http://www.cs.swan.ac.uk/~csetzer/
---------------------------------------
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.chalmers.se/mailman/private/agda/attachments/20080607/e717ed6c/attachment-0001.html
More information about the Agda
mailing list