I was messing around with induction stuff again and some stuff seems to require bisimilarity relations instead of just equality when dualizing for coinductive types.
CoInductive stream A := {
head: A ;
tail: stream A ;
}.
Arguments head {A}.
Arguments tail {A}.
Requires something like
CoInductive eq_stream {A} (x y: stream A) := {
eq_head: head x = head y ;
eq_tail: eq_stream (tail x) (tail y) ;
}.
I vaguely recall a little about bisimulation and coinductive types but I would really like if someone could explain the situation in detail.
I understand the situation is a little like extensionality for functions but I don't quite get the details why. Maybe a system like Cubical Agda doesn't require the same workarounds?
I vaguely recall it's consistent to add an axiom like Axiom bisim: forall {A} (x y: stream A) -> eq_stream x y -> x = y.
But this is a bit ad-hoc.
You can maybe use M types/containers for a single generic axiom. Something like the following where there's a small amount of annoyance rewriting a dependent field I didn't want to figure out right now.
CoInductive M {A} (B: A -> Type) := {
tag: A ;
field (x: B tag): M B ;
}.
Arguments tag {A B}.
Arguments field {A B}.
CoInductive M_eq {A} {B: A -> Type} (x y: M B):= {
eq_tag: tag x = tag y ;
eq_field f: M_eq (field x f) (field (rw eq_tag y) f) ;
}.
Axiom bisim: forall {A} {B -> Type} (x y: M B), M_eq x y -> x = y.
But I'm definitely not sure of all the details of this. Not at all sure universe polymorphism would make this generic enough either.
Why do coinductive types require bisimilarity relations? And given for now we have to work around it what's the best way of doing so?
Axiom eta: forall A (B: A -> Type) (x: M B), x = {| tag := tag x ; field := field x |}.
. $\endgroup$