Say I have two inductively defined datatypes:
Inductive list1 (A : Type) : Type :=
| nil1 : list1 A
| cons1 : A -> list1 A -> list1 A.
and
Inductive list2 (A : Type) : Type :=
| nil2 : list2 A
| cons2 : A -> list2 A -> list2 A.
For any P (list1 a)
I should be able to construct a P (list2 a)
, by applying the exact same method I used to construct P (list1 a)
except replacing nil1
with nil2
, list1
with list2
and cons1
with cons2
. Similarly, any function that takes list1 a
as a parameter could be extended to take a list2 a
.
Is there a type system that allows me to speak of two datatypes having the same shape in this manner (having identically shaped constructors), and prove P (list1 a) -> P (list2 a)
? For instance, is this something that univalence, HOTT, or a cubical/observational type system allows? It might also allow defining functions like reverse: list_like a -> list_like a
that accept both list1
s and list2
s as parameters.