ListP t
und ListI t
sind isomorph: Sie haben genau die gleichen Konstruktoren.
<prompt>Coq < 12 || 0 < </prompt>Check (NilP, NilI).
(NilP, NilI)
: (forall t : Type, ListP t) *
(forall t : Type, ListI t)
<prompt>Coq < 13 || 0 < </prompt>Check (ConsP, ConsI).
(ConsP, ConsI)
: (forall t : Type, t -> ListP t -> ListP t) *
(forall t : Type, t -> ListI t -> ListI t)
Coq erzeugt jedoch unterschiedliche Induktionsprinzipien.
<prompt>Coq < 14 || 0 < </prompt>Check (ListP_ind, ListI_ind).
(ListP_ind, ListI_ind)
: (forall (t : Type) (P : ListP t -> Prop),
P (NilP t) ->
(forall (t0 : t) (l : ListP t), P l -> P (ConsP t t0 l)) ->
forall l : ListP t, P l) *
(forall P : forall T : Type, ListI T -> Prop,
(forall t : Type, P t (NilI t)) ->
(forall (t : Type) (t0 : t) (l : ListI t),
P t l -> P t (ConsI t t0 l)) ->
forall (T : Type) (l : ListI T), P T l)
Das Induktionsprinzip von ListI
erfordert, dass die Eigenschaft im Elementtyp ( P : forall T, ListI T -> Prop
) parametrisch ist, während das Induktionsprinzip von ListP
bei jedem Typ t
( P : ListP t -> Prop
) instanziiert werden kann . Dies ist eine Schwäche von Coqs Front-End, da ungleichmäßige rekursive Typen nicht klug sind. Sie können dasselbe Induktionsprinzip manuell definieren (der Typechecker akzeptiert es, was nicht überraschend ist, da es ListP_ind
durch den offensichtlichen Isomorphismus zwischen ListP
und transformiert wird ListI
).
Das parametrische Formular ListP
ist einfacher und sofort einsatzbereit. Das ListI
Formular kann auf eine ungleichmäßige Rekursion verallgemeinert werden, bei der die Parameter in den rekursiven Aufrufen nicht das Original sind. Ein Beispiel finden Sie unter Polymorphismus und induktive Datentypen .