Рассмотрим следующий код:
Require Import List.
Set Implicit Arguments.
Inductive even_length {A : Type} : list A -> Prop:=
| e_nil : even_length nil
| e_cons : forall e l, odd_length l -> even_length (e::l)
with
odd_length {A : Type} : list A -> Prop :=
| o_cons : forall e l, even_length l -> odd_length (e::l).
Lemma map_even : forall A B (f : A -> B) (l : list A),
even_length l -> even_length (map f l).
Proof.
induction l.
(** nil *)
- intros. simpl. econstructor.
(** cons *)
- intros. simpl.
inversion_clear H.
econstructor.
Abort. (** odd_length l -> odd_length (map f l) would help *)
Обратите внимание, что я хочу доказать это с индукцией по списку l
.
Как объяснено в здесь ,Coq по умолчанию генерирует только принципы взаимной индукции, и для получения принципов взаимной индукции необходима команда Scheme
.Вот что я сделал:
Scheme even_length_mut := Induction for even_length Sort Prop
with odd_length_mut := Induction for odd_length Sort Prop.
Check even_length_mut.
(**
even_length_mut
: forall (A : Type) (P : forall l : list A, even_length l -> Prop) (P0 : forall l : list A, odd_length l -> Prop),
P nil e_nil ->
(forall (e : A) (l : list A) (o : odd_length l), P0 l o -> P (e :: l) (e_cons e o)) ->
(forall (e : A) (l : list A) (e0 : even_length l), P l e0 -> P0 (e :: l) (o_cons e e0)) -> forall (l : list A) (e : even_length l), P l e
*)
Из приведенного выше типа и примеров, которые я видел, мне удалось завершить это доказательство примерно так:
Lemma map_even : forall A B (f : A -> B) (l : list A),
even_length l -> even_length (map f l).
Proof.
intros.
apply (even_length_mut (fun l (h : even_length l) => even_length (map f l) )
(fun l (h : odd_length l) => odd_length (map f l) )
);
try econstructor; auto.
Qed.
Однако эта индукция не былане более l
, это была так называемая «индукция по свидетельству».
Мой вопрос: какими должны быть предикаты в even_length_mut
, чтобы индукция превышала l
?
Редактировать: Кроме того, было бы возможно получить гипотезу odd_length l -> odd_length (map f l)
?