(* Intended for use without Import. *)
Set Implicit Arguments.
Unset Automatic Introduction.
Require ne_list.
Require List.
Section contents.
Variable E: Set.
Unset Elimination Schemes.
Inductive T: Set :=
| Leaf: E -> T
| Node: ne_list.L T -> T.
Set Elimination Schemes.
Definition fold (Y: Set) (f: E -> Y) (g: ne_list.L Y -> Y): T -> Y :=
fix F (t: T) :=
match t with
| Leaf e => f e
| Node l => g (ne_list.map F l)
end.
Definition T_rect (P: T -> Type) (Pleaf: forall n, P (Leaf n)) (Pone: forall t, P t -> P (Node (ne_list.one t))) (Pcons: forall t l, P t -> P (Node l) -> P (Node (ne_list.cons t l))): forall t, P t :=
fix F (t: T) :=
match t return P t with
| Leaf n => Pleaf n
| Node l => (fix G (r: ne_list.L T) :=
match r return P (Node r) with
| ne_list.one x => Pone x (F x)
| ne_list.cons x y => Pcons x y (F x) (G y)
end) l
end.
Definition T_ind (P: T -> Prop) (Pleaf: forall n, P (Leaf n)) (Pone: forall t, P t -> P (Node (ne_list.one t))) (Pcons: forall t l, P t -> P (Node l) -> P (Node (ne_list.cons t l))): forall t, P t := T_rect P Pleaf Pone Pcons.
Definition T_rec (P: T -> Set) (Pleaf: forall n, P (Leaf n)) (Pone: forall t, P t -> P (Node (ne_list.one t))) (Pcons: forall t l, P t -> P (Node l) -> P (Node (ne_list.cons t l))): forall t, P t := T_rect P Pleaf Pone Pcons.
Definition alt_ind (P: T -> Prop) (Pleaf: forall n, P (Leaf n)) (Pnode: forall l:ne_list.L T, (forall t, List.In t l -> P t) -> P (Node l)) (t: T): P t .
Proof with auto.
intros P Hbase Hrcd.
refine (fix IH (t:T) {struct t} : P t := _).
destruct t.
apply Hbase.
apply Hrcd.
induction l.
simpl.
intros.
destruct H.
rewrite <- H.
apply IH.
elimtype False.
exact H.
simpl.
intros.
destruct H.
rewrite <- H.
apply IH.
apply IHl.
assumption.
Qed.
Section alt_rect2.
Variable P: T -> Type.
Variable Q: ne_list.L T -> Type.
Variable Pleaf: forall n, P (Leaf n).
Variable Pnode: forall l, Q l -> P (Node l).
Variable Qone: forall t, P t -> Q (ne_list.one t).
Variable Qcons: forall t l, P t -> Q l -> Q (ne_list.cons t l).
Fixpoint alt_rect2 (t: T): P t :=
match t return P t with
| Leaf x => Pleaf x
| Node l => Pnode ((fix F (l: ne_list.L T) :=
match l return Q l with
| ne_list.one t => Qone (alt_rect2 t)
| ne_list.cons x y => @Qcons x y (alt_rect2 x) (F y)
end) l)
end.
End alt_rect2.
Definition alt_ind2
(P: T -> Prop) (Q: ne_list.L T -> Prop)
(Pleaf: forall n, P (Leaf n))
(Pnode: forall l, Q l -> P (Node l))
(Qone: forall t, P t -> Q (ne_list.one t))
(Qcons: forall t l, P t -> Q l -> Q (ne_list.cons t l)): forall t, P t
:= alt_rect2 P Q Pleaf Pnode Qone Qcons.
Definition alt_rec2
(P: T -> Set) (Q: ne_list.L T -> Set)
(Pleaf: forall n, P (Leaf n))
(Pnode: forall l, Q l -> P (Node l))
(Qone: forall t, P t -> Q (ne_list.one t))
(Qcons: forall t l, P t -> Q l -> Q (ne_list.cons t l)): forall t, P t
:= alt_rect2 P Q Pleaf Pnode Qone Qcons.
Fixpoint head (t: T): E :=
match t with
| Leaf e => e
| Node l => head (ne_list.head l)
end.
Inductive In (e: E): T -> Prop :=
| InLeaf: In e (Leaf e)
| InNode l: InL e l -> In e (Node l)
with InL (e: E): ne_list.L T -> Prop :=
| InOne t: In e t -> InL e (ne_list.one t)
| InHead t l: In e t -> InL e (ne_list.cons t l)
| InTail t l: InL e l -> InL e (ne_list.cons t l).

Lemma InL_map_inv (Q: Set) (e: E) (f: Q -> T) (l: ne_list.L Q):
InL e (ne_list.map f l) -> exists e', In e (f e') /\ List.In e' l.