ListP t
và ListI t
đẳng cấu: chúng có cùng các hàm tạo.
<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)
Tuy nhiên Coq tạo ra các nguyên tắc cảm ứng khác nhau.
<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)
Nguyên tắc cảm ứng ListI
đòi hỏi thuộc tính phải là tham số trong loại phần tử ( P : forall T, ListI T -> Prop
) trong khi nguyên tắc cảm ứng ListP
có thể được khởi tạo ở bất kỳ loại nào t
( P : ListP t -> Prop
). Đây là một điểm yếu của front-end của Coq, ở chỗ nó không thông minh về các loại đệ quy không đồng nhất; bạn có thể định nghĩa thủ công cùng một nguyên tắc cảm ứng (máy đánh chữ chấp nhận nó, điều này không có gì đáng ngạc nhiên khi nó được ListP_ind
biến đổi bởi sự đẳng cấu rõ ràng giữa ListP
và ListI
).
Các hình thức tham số ListP
là đơn giản và dễ dàng hơn để sử dụng ra khỏi hộp. Biểu ListI
mẫu có thể khái quát thành đệ quy không đồng nhất, trong đó các tham số trong các cuộc gọi đệ quy không phải là bản gốc. Xem ví dụ về đa hình và kiểu dữ liệu quy nạp .