Built with Alectryon, running Coq+SerAPI v8.16.0+0.16.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.

Formalizing STLC with Tealeaves

Algebraic presentation

This file gives a tutorial on proving the decorated traversable monad laws the for the syntax of the simply-typed lambda calculus (STLC).

Imports and setup

Since we are using the algebraic typeclass hierarchy, we import modules under the namespaces Classes.Algebraic and Theory.Algebraic.

From Tealeaves Require Export
  Classes.Categorical.DecoratedTraversableMonad
  Classes.Monoid
  Functors.Writer
  Misc.NaturalNumbers.

Import Categorical.TraversableFunctor.Notations.
Import List.ListNotations.
Import Strength.Notations.
Import Monoid.Notations.

#[local] Generalizable All Variables.
#[local] Set Implicit Arguments.

Language Definition

The first step with Tealeaves is to define the syntax of the language. We take a type base_typ of types we consider primitive (a/k/a atomic). The set of simple types is built up by forming arrows between types, starting with base types. The syntax of STLC is defined with three constructors as usual.

Parameter base_typ: Type.

Inductive typ :=
| base: base_typ -> typ
| arr: typ -> typ -> typ.

Coercion base: base_typ >-> typ.

(* we give more informative names to [Lam]'s arguments
 than Coq would infer otherwise *)
Inductive term (A: Type) :=
| Var: A -> term A
| Lam: forall (X: typ) (t: term A), term A
| Ap: term A -> term A -> term A.

Module Notations.
  Notation "'λ' X ⋅ body" :=
    (Lam X body) (at level 45): tealeaves_scope.
  Notation "[ t1 ] [ t2 ]" :=
    (Ap t1 t2) (at level 40): tealeaves_scope.
  Notation "A ⟹ B" :=
    (arr A B) (at level 40): tealeaves_scope.
End Notations.

Import Notations.

For convenience, we define an extremely rudimentary Ltac tactic that will solve the most trivial inductive steps automatically. Namely, they will attempt to solve a goal in one step by rewriting with the hypotheses in context (up to two times), then calling reflexivity.

Ltac basic t :=
  induction t;
  [ reflexivity |
    simpl; match goal with H: _ |- _ => rewrite H end; reflexivity |
    simpl; do 2 match goal with H: _ |- _ => rewrite H end; reflexivity ].

Functor instances

Plain Functor instance

Note that our datatype term is parameterized by a single type variable. The first thing we must show is that term is actually functor in this type argument.

Fixpoint map_term {A B: Type} (f: A -> B) (t: term A): term B :=
  match t with
  | Var a => Var (f a)
  | Lam X t => Lam X (map_term f t)
  | Ap t1 t2 => Ap (map_term f t1) (map_term f t2)
  end.

#[export] Instance Map_term: Map term := @map_term.


forall A : Type, map id = id

forall A : Type, map id = id
A: Type

map id = id
A: Type
t: term A

map id t = id t
A: Type
t: term A

map_term id t = id t
basic t. Qed.

forall (A B C : Type) (f : A -> B) (g : B -> C), map g ∘ map f = map (g ∘ f)

forall (A B C : Type) (f : A -> B) (g : B -> C), map g ∘ map f = map (g ∘ f)
A, B, C: Type
f: A -> B
g: B -> C

map g ∘ map f = map (g ∘ f)
A, B, C: Type
f: A -> B
g: B -> C
t: term A

(map g ∘ map f) t = map (g ∘ f) t
A, B, C: Type
f: A -> B
g: B -> C
t: term A

(map_term g ∘ map_term f) t = map_term (g ∘ f) t
A, B, C: Type
f: A -> B
g: B -> C
t: term A

map_term g (map_term f t) = map_term (g ○ f) t
basic t. Qed. #[export] Instance Functor_term: Functor term := {| fun_map_id := @map_id; fun_map_map := @map_map; |}.

Rewriting rules for map

Section map_term_rewrite.

  Context
    `{f: A -> B}.

  
A, B: Type
f: A -> B

forall t1 t2 : term A, map f ([t1][t2]) = [map f t1][map f t2]
A, B: Type
f: A -> B

forall t1 t2 : term A, map f ([t1][t2]) = [map f t1][map f t2]
reflexivity. Qed. End map_term_rewrite.

Decorated Functor instance

Fixpoint dec_term {A} (t: term A): term (nat * A) :=
  match t with
  | Var a => Var (Ƶ, a)
  | Lam τ t => Lam τ (shift term (1, dec_term t))
  | Ap t1 t2 => Ap (dec_term t1) (dec_term t2)
  end.

#[export] Instance Decorate_term: Decorate nat term := @dec_term.


forall (A B : Type) (f : A -> B), map (map f) ∘ dec term = dec term ∘ map f

forall (A B : Type) (f : A -> B), map (map f) ∘ dec term = dec term ∘ map f
A, B: Type
f: A -> B

map (map f) ∘ dec term = dec term ∘ map f
A, B: Type
f: A -> B

map (map f) ○ dec term = dec term ○ map f
A, B: Type
f: A -> B
t: term A

map (map f) (dec term t) = dec term (map f t)
A, B: Type
f: A -> B
a: A

map (map f) (dec term (Var a)) = dec term (map f (Var a))
A, B: Type
f: A -> B
X: typ
t: term A
IHt: map (map f) (dec term t) = dec term (map f t)
map (map f) (dec term (λ X ⋅ t)) = dec term (map f (λ X ⋅ t))
A, B: Type
f: A -> B
t1, t2: term A
IHt1: map (map f) (dec term t1) = dec term (map f t1)
IHt2: map (map f) (dec term t2) = dec term (map f t2)
map (map f) (dec term ([t1][t2])) = dec term (map f ([t1][t2]))
A, B: Type
f: A -> B
a: A

map (map f) (dec term (Var a)) = dec term (map f (Var a))
now cbn.
A, B: Type
f: A -> B
X: typ
t: term A
IHt: map (map f) (dec term t) = dec term (map f t)

map (map f) (dec term (λ X ⋅ t)) = dec term (map f (λ X ⋅ t))
A, B: Type
f: A -> B
X: typ
t: term A
IHt: map (map f) (dec term t) = dec term (map f t)

λ X ⋅ map (map f) (shift term (1, dec term t)) = λ X ⋅ shift term (1, dec term (map f t))
A, B: Type
f: A -> B
X: typ
t: term A
IHt: map (map f) (dec term t) = dec term (map f t)

map (map f) (shift term (1, dec term t)) = shift term (1, dec term (map f t))
now rewrite dec_helper_1.
A, B: Type
f: A -> B
t1, t2: term A
IHt1: map (map f) (dec term t1) = dec term (map f t1)
IHt2: map (map f) (dec term t2) = dec term (map f t2)

map (map f) (dec term ([t1][t2])) = dec term (map f ([t1][t2]))
A, B: Type
f: A -> B
t1, t2: term A
IHt1: map (map f) (dec term t1) = dec term (map f t1)
IHt2: map (map f) (dec term t2) = dec term (map f t2)

[map (map f) (dec term t1)][map (map f) (dec term t2)] = [dec term (map f t1)][dec term (map f t2)]
now fequal. Qed.

Natural (@dec nat term Decorate_term)

Natural (@dec nat term Decorate_term)

Functor term

Functor (term ○ prod nat)

forall (A B : Type) (f : A -> B), map f ∘ dec term = dec term ∘ map f

Functor term
typeclasses eauto.

Functor (term ○ prod nat)
apply Functor_compose; typeclasses eauto.

forall (A B : Type) (f : A -> B), map f ∘ dec term = dec term ∘ map f
apply dec_natural. Qed.

forall A : Type, map extract ∘ dec term = id

forall A : Type, map extract ∘ dec term = id
A: Type

map extract ∘ dec term = id
A: Type

map extract ○ dec term = id
A: Type
t: term A

map extract (dec term t) = id t
A: Type
a: A

map extract (dec term (Var a)) = id (Var a)
A: Type
X: typ
t: term A
IHt: map extract (dec term t) = id t
map extract (dec term (λ X ⋅ t)) = id (λ X ⋅ t)
A: Type
t1, t2: term A
IHt1: map extract (dec term t1) = id t1
IHt2: map extract (dec term t2) = id t2
map extract (dec term ([t1][t2])) = id ([t1][t2])
A: Type
a: A

map extract (dec term (Var a)) = id (Var a)
reflexivity.
A: Type
X: typ
t: term A
IHt: map extract (dec term t) = id t

map extract (dec term (λ X ⋅ t)) = id (λ X ⋅ t)
A: Type
X: typ
t: term A
IHt: map extract (dec term t) = id t

λ X ⋅ map extract (shift term (1, dec term t)) = id (λ X ⋅ t)
now rewrite dec_helper_2.
A: Type
t1, t2: term A
IHt1: map extract (dec term t1) = id t1
IHt2: map extract (dec term t2) = id t2

map extract (dec term ([t1][t2])) = id ([t1][t2])
A: Type
t1, t2: term A
IHt1: map extract (dec term t1) = id t1
IHt2: map extract (dec term t2) = id t2

map extract (dec term ([t1][t2])) = [t1][t2]
A: Type
t1, t2: term A
IHt1: map extract (dec term t1) = id t1
IHt2: map extract (dec term t2) = id t2

[map extract (dec term t1)][map extract (dec term t2)] = [t1][t2]
now fequal. Qed.

forall A : Type, dec term ∘ dec term = map cojoin ∘ dec term

forall A : Type, dec term ∘ dec term = map cojoin ∘ dec term
A: Type

dec term ∘ dec term = map cojoin ∘ dec term
A: Type

dec term ○ dec term = map cojoin ○ dec term
A: Type
t: term A

dec term (dec term t) = map cojoin (dec term t)
A: Type
a: A

dec term (dec term (Var a)) = map cojoin (dec term (Var a))
A: Type
X: typ
t: term A
IHt: dec term (dec term t) = map cojoin (dec term t)
dec term (dec term (λ X ⋅ t)) = map cojoin (dec term (λ X ⋅ t))
A: Type
t1, t2: term A
IHt1: dec term (dec term t1) = map cojoin (dec term t1)
IHt2: dec term (dec term t2) = map cojoin (dec term t2)
dec term (dec term ([t1][t2])) = map cojoin (dec term ([t1][t2]))
A: Type
a: A

dec term (dec term (Var a)) = map cojoin (dec term (Var a))
reflexivity.
A: Type
X: typ
t: term A
IHt: dec term (dec term t) = map cojoin (dec term t)

dec term (dec term (λ X ⋅ t)) = map cojoin (dec term (λ X ⋅ t))
A: Type
X: typ
t: term A
IHt: dec term (dec term t) = map cojoin (dec term t)

λ X ⋅ shift term (1, dec term (shift term (1, dec term t))) = λ X ⋅ map cojoin (shift term (1, dec term t))
A: Type
X: typ
t: term A
IHt: dec term (dec term t) = map cojoin (dec term t)

shift term (1, dec term (shift term (1, dec term t))) = map cojoin (shift term (1, dec term t))
now rewrite dec_helper_3.
A: Type
t1, t2: term A
IHt1: dec term (dec term t1) = map cojoin (dec term t1)
IHt2: dec term (dec term t2) = map cojoin (dec term t2)

dec term (dec term ([t1][t2])) = map cojoin (dec term ([t1][t2]))
A: Type
t1, t2: term A
IHt1: dec term (dec term t1) = map cojoin (dec term t1)
IHt2: dec term (dec term t2) = map cojoin (dec term t2)

[dec term (dec term t1)][dec term (dec term t2)] = [map cojoin (dec term t1)][map cojoin (dec term t2)]
fequal; auto. Qed.

DecoratedFunctor nat term

DecoratedFunctor nat term

Functor term

Natural (@dec nat term Decorate_term)

forall A : Type, dec term ∘ dec term = map cojoin ∘ dec term

forall A : Type, map extract ∘ dec term = id

Functor term
typeclasses eauto.

Natural (@dec nat term Decorate_term)
typeclasses eauto.

forall A : Type, dec term ∘ dec term = map cojoin ∘ dec term
apply dec_dec.

forall A : Type, map extract ∘ dec term = id
apply dec_extract. Qed.

Rewriting rules for dec

Section dec_term_rewrite.

  Context
    `{f: A -> B}.

  
A, B: Type
f: A -> B

forall x : A, dec term (Var x) = Var (0, x)
A, B: Type
f: A -> B

forall x : A, dec term (Var x) = Var (0, x)
reflexivity. Qed.
A, B: Type
f: A -> B

forall (X : typ) (t : term A), dec term (λ X ⋅ t) = shift term (1, λ X ⋅ dec term t)
A, B: Type
f: A -> B

forall (X : typ) (t : term A), dec term (λ X ⋅ t) = shift term (1, λ X ⋅ dec term t)
reflexivity. Qed.
A, B: Type
f: A -> B

forall (X : typ) (t : term A), dec term (λ X ⋅ t) = λ X ⋅ shift term (1, dec term t)
A, B: Type
f: A -> B

forall (X : typ) (t : term A), dec term (λ X ⋅ t) = λ X ⋅ shift term (1, dec term t)
reflexivity. Qed.
A, B: Type
f: A -> B

forall t1 t2 : term A, dec term ([t1][t2]) = [dec term t1][dec term t2]
A, B: Type
f: A -> B

forall t1 t2 : term A, dec term ([t1][t2]) = [dec term t1][dec term t2]
reflexivity. Qed. End dec_term_rewrite.

Traversable Functor instance

Import Applicative.Notations.

Fixpoint dist_term `{Map F} `{Pure F} `{Mult F} {A: Type}
         (t: term (F A)): F (term A) :=
  match t with
  | Var a => map (@Var A) a
  | Lam X t => map (Lam X) (dist_term t)
  | Ap t1 t2 => (pure (@Ap A))
                 <⋆> dist_term t1
                 <⋆> dist_term t2
  end.

#[export] Instance: ApplicativeDist term := @dist_term.

Rewriting rules for dist

Section term_dist_rewrite.

  Context
    `{Applicative G}.

  Variable (A: Type).

  
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall x : G A, δ term G (Var x) = pure (Var (A:=A)) <⋆> x
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall x : G A, δ term G (Var x) = pure (Var (A:=A)) <⋆> x
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
x: G A

δ term G (Var x) = pure (Var (A:=A)) <⋆> x
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
x: G A

map (Var (A:=A)) x = pure (Var (A:=A)) <⋆> x
now rewrite map_to_ap. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall x : G A, δ term G (Var x) = map (Var (A:=A)) x
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall x : G A, δ term G (Var x) = map (Var (A:=A)) x
reflexivity. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall (X : typ) (t : term (G A)), δ term G (λ X ⋅ t) = pure (Lam X) <⋆> δ term G t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall (X : typ) (t : term (G A)), δ term G (λ X ⋅ t) = pure (Lam X) <⋆> δ term G t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)

δ term G (λ X ⋅ t) = pure (Lam X) <⋆> δ term G t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)

map (Lam X) (δ term G t) = pure (Lam X) <⋆> δ term G t
now rewrite map_to_ap. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall (X : typ) (t : term (G A)), δ term G (λ X ⋅ t) = map (Lam X) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall (X : typ) (t : term (G A)), δ term G (λ X ⋅ t) = map (Lam X) (δ term G t)
reflexivity. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall t1 t2 : term (G A), δ term G ([t1][t2]) = pure (Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall t1 t2 : term (G A), δ term G ([t1][t2]) = pure (Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2
reflexivity. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall t1 t2 : term (G A), δ term G ([t1][t2]) = map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

forall t1 t2 : term (G A), δ term G ([t1][t2]) = map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)

δ term G ([t1][t2]) = map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)

pure (Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2 = map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
now rewrite map_to_ap. Qed. End term_dist_rewrite. Section dist_term_properties. Context `{Applicative G}.

Naturality of dist

  
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (A B : Type) (f : A -> B), map f ∘ δ term G = δ term G ∘ map f
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (A B : Type) (f : A -> B), map f ∘ δ term G = δ term G ∘ map f
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B

map f ∘ δ term G = δ term G ∘ map f
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t: term (G A)

(map f ∘ δ term G) t = (δ term G ∘ map f) t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t: term (G A)

(map (map f) ∘ δ term G) t = (δ term G ∘ map (map f)) t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t: term (G A)

map (map f) (δ term G t) = δ term G (map (map f) t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
a: G A

map (map f) (δ term G (Var a)) = δ term G (map (map f) (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
X: typ
t: term (G A)
IHt: map (map f) (δ term G t) = δ term G (map (map f) t)
map (map f) (δ term G (λ X ⋅ t)) = δ term G (map (map f) (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)
map (map f) (δ term G ([t1][t2])) = δ term G (map (map f) ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
a: G A

map (map f) (δ term G (Var a)) = δ term G (map (map f) (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
a: G A

map (map f) (map (Var (A:=A)) a) = map (Var (A:=B)) (map f a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
a: G A

(map (map f) ∘ map (Var (A:=A))) a = (map (Var (A:=B)) ∘ map f) a
now rewrite 2(fun_map_map).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
X: typ
t: term (G A)
IHt: map (map f) (δ term G t) = δ term G (map (map f) t)

map (map f) (δ term G (λ X ⋅ t)) = δ term G (map (map f) (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
X: typ
t: term (G A)
IHt: map (map f) (δ term G t) = δ term G (map (map f) t)

map (map f) (map (Lam X) (δ term G t)) = map (Lam X) (δ term G (map (map f) t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
X: typ
t: term (G A)
IHt: map (map f) (δ term G t) = δ term G (map (map f) t)

map (map f) (map (Lam X) (δ term G t)) = map (Lam X) (map (map f) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
X: typ
t: term (G A)
IHt: map (map f) (δ term G t) = δ term G (map (map f) t)

(map (map f) ∘ map (Lam X)) (δ term G t) = (map (Lam X) ∘ map (map f)) (δ term G t)
now rewrite 2(fun_map_map).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (δ term G ([t1][t2])) = δ term G (map (map f) ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2) = δ term G (map (map f) ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2) = δ term G ([map (map f) t1][map (map f) t2])
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2) = map (Ap (A:=B)) (δ term G (map (map f) t1)) <⋆> δ term G (map (map f) t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2) = map (Ap (A:=B)) (map (map f) (δ term G t1)) <⋆> map (map f) (δ term G t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (map f) (map (Ap (A:=A)) (δ term G t1) <⋆> δ term G t2) = map (precompose (map f)) (map (Ap (A:=B)) (map (map f) (δ term G t1))) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f)) (map (Ap (A:=A)) (δ term G t1)) <⋆> δ term G t2 = map (precompose (map f)) (map (Ap (A:=B)) (map (map f) (δ term G t1))) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f)) (map (Ap (A:=A)) (δ term G t1)) = map (precompose (map f)) (map (Ap (A:=B)) (map (map f) (δ term G t1)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

(map (compose (map f)) ∘ map (Ap (A:=A))) (δ term G t1) = map (precompose (map f)) ((map (Ap (A:=B)) ∘ map (map f)) (δ term G t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f) ∘ Ap (A:=A)) (δ term G t1) = map (precompose (map f)) ((map (Ap (A:=B)) ∘ map (map f)) (δ term G t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f) ∘ Ap (A:=A)) (δ term G t1) = map (precompose (map f)) (map (Ap (A:=B) ∘ map f) (δ term G t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f) ∘ Ap (A:=A)) (δ term G t1) = (map (precompose (map f)) ∘ map (Ap (A:=B) ∘ map f)) (δ term G t1)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B
t1, t2: term (G A)
IHt1: map (map f) (δ term G t1) = δ term G (map (map f) t1)
IHt2: map (map f) (δ term G t2) = δ term G (map (map f) t2)

map (compose (map f) ∘ Ap (A:=A)) (δ term G t1) = map (precompose (map f) ∘ (Ap (A:=B) ∘ map f)) (δ term G t1)
reflexivity. Qed.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Natural (@dist term ApplicativeDist_instance_0 G Map_G Pure_G Mult_G)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Natural (@dist term ApplicativeDist_instance_0 G Map_G Pure_G Mult_G)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Natural (@dist term ApplicativeDist_instance_0 G Map_G Pure_G Mult_G)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Functor (term ○ G)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
Functor (G ○ term)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
forall (A B : Type) (f : A -> B), map f ∘ δ term G = δ term G ∘ map f
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Functor (term ○ G)
typeclasses eauto.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

Functor (G ○ term)
typeclasses eauto.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (A B : Type) (f : A -> B), map f ∘ δ term G = δ term G ∘ map f
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A, B: Type
f: A -> B

map f ∘ δ term G = δ term G ∘ map f
apply dist_natural_term. Qed.

Traversal laws

  
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term (fun A0 : Type => A0) = id
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term (fun A0 : Type => A0) = id
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

δ term (fun A : Type => A) = id
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t: term A

δ term (fun A : Type => A) t = id t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: A

δ term (fun A : Type => A) (Var a) = id (Var a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term A
IHt: δ term (fun A : Type => A) t = id t
δ term (fun A : Type => A) (λ X ⋅ t) = id (λ X ⋅ t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term A
IHt1: δ term (fun A : Type => A) t1 = id t1
IHt2: δ term (fun A : Type => A) t2 = id t2
δ term (fun A : Type => A) ([t1][t2]) = id ([t1][t2])
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: A

δ term (fun A : Type => A) (Var a) = id (Var a)
reflexivity.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term A
IHt: δ term (fun A : Type => A) t = id t

δ term (fun A : Type => A) (λ X ⋅ t) = id (λ X ⋅ t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term A
IHt: δ term (fun A : Type => A) t = id t

map (Lam X) (δ term (fun A : Type => A) t) = id (λ X ⋅ t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term A
IHt: δ term (fun A : Type => A) t = id t

map (Lam X) (id t) = id (λ X ⋅ t)
reflexivity.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term A
IHt1: δ term (fun A : Type => A) t1 = id t1
IHt2: δ term (fun A : Type => A) t2 = id t2

δ term (fun A : Type => A) ([t1][t2]) = id ([t1][t2])
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term A
IHt1: δ term (fun A : Type => A) t1 = id t1
IHt2: δ term (fun A : Type => A) t2 = id t2

pure (Ap (A:=A)) (δ term (fun A : Type => A) t1) (δ term (fun A : Type => A) t2) = id ([t1][t2])
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term A
IHt1: δ term (fun A : Type => A) t1 = id t1
IHt2: δ term (fun A : Type => A) t2 = id t2

pure (Ap (A:=A)) (id t1) (id t2) = id ([t1][t2])
reflexivity. Qed. #[local] Set Keyed Unification.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (G1 : Type -> Type) (Map_G0 : Map G1) (Pure_G0 : Pure G1) (Mult_G0 : Mult G1), Applicative G1 -> forall (G2 : Type -> Type) (Map_G1 : Map G2) (Pure_G1 : Pure G2) (Mult_G1 : Mult G2), Applicative G2 -> forall A : Type, δ term (G1 ∘ G2) = map (δ term G2) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (G1 : Type -> Type) (Map_G0 : Map G1) (Pure_G0 : Pure G1) (Mult_G0 : Mult G1), Applicative G1 -> forall (G2 : Type -> Type) (Map_G1 : Map G2) (Pure_G1 : Pure G2) (Mult_G1 : Mult G2), Applicative G2 -> forall A : Type, δ term (G1 ∘ G2) = map (δ term G2) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type

δ term (G1 ∘ G2) = map (δ term G2) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type

δ term (G1 ○ G2) = map (δ term G2) ○ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t: term (G1 (G2 A))

δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
a: G1 (G2 A)

δ term (G1 ○ G2) (Var a) = map (δ term G2) (δ term G1 (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)
δ term (G1 ○ G2) (λ X ⋅ t) = map (δ term G2) (δ term G1 (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)
δ term (G1 ○ G2) ([t1][t2]) = map (δ term G2) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
a: G1 (G2 A)

δ term (G1 ○ G2) (Var a) = map (δ term G2) (δ term G1 (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
a: G1 (G2 A)

map (Var (A:=A)) a = map (δ term G2) (map (Var (A:=G2 A)) a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
a: G1 (G2 A)

map (Var (A:=A)) a = (map (δ term G2) ∘ map (Var (A:=G2 A))) a
now rewrite (fun_map_map).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

δ term (G1 ○ G2) (λ X ⋅ t) = map (δ term G2) (δ term G1 (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

map (Lam X) (δ term (G1 ○ G2) t) = map (δ term G2) (map (Lam X) (δ term G1 t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

map (Lam X) (map (δ term G2) (δ term G1 t)) = map (δ term G2) (map (Lam X) (δ term G1 t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

(map (Lam X) ∘ map (δ term G2)) (δ term G1 t) = (map (δ term G2) ∘ map (Lam X)) (δ term G1 t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

(map (map (Lam X)) ∘ map (δ term G2)) (δ term G1 t) = (map (δ term G2) ∘ map (Lam X)) (δ term G1 t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
X: typ
t: term (G1 (G2 A))
IHt: δ term (G1 ○ G2) t = map (δ term G2) (δ term G1 t)

map (map (Lam X) ∘ δ term G2) (δ term G1 t) = (map (δ term G2) ∘ map (Lam X)) (δ term G1 t)
now rewrite (fun_map_map).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

δ term (G1 ○ G2) ([t1][t2]) = map (δ term G2) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

δ term (G1 ○ G2) ([t1][t2]) = map (δ term G2) (map (Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (Ap (A:=A)) (δ term (G1 ○ G2) t1) <⋆> δ term (G1 ○ G2) t2 = map (δ term G2) (map (Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (Ap (A:=A)) (δ term (G1 ○ G2) t1) <⋆> δ term (G1 ○ G2) t2 = map (compose (δ term G2)) (map (Ap (A:=G2 A)) (δ term G1 t1)) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (Ap (A:=A)) (δ term (G1 ○ G2) t1) <⋆> δ term (G1 ○ G2) t2 = (map (compose (δ term G2)) ∘ map (Ap (A:=G2 A))) (δ term G1 t1) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (Ap (A:=A)) (δ term (G1 ○ G2) t1) <⋆> δ term (G1 ○ G2) t2 = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (ap G2) (map (Ap (A:=A)) (δ term (G1 ○ G2) t1)) <⋆> δ term (G1 ○ G2) t2 = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (ap G2) (map (Ap (A:=A)) (map (δ term G2) (δ term G1 t1))) <⋆> map (δ term G2) (δ term G1 t2) = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (precompose (δ term G2)) (map (ap G2) (map (Ap (A:=A)) (map (δ term G2) (δ term G1 t1)))) <⋆> δ term G1 t2 = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1) <⋆> δ term G1 t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (precompose (δ term G2)) (map (ap G2) (map (Ap (A:=A)) (map (δ term G2) (δ term G1 t1)))) = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

map (precompose (δ term G2) ∘ (ap G2 ∘ (map (Ap (A:=A)) ∘ δ term G2))) (δ term G1 t1) = map (compose (δ term G2) ∘ Ap (A:=G2 A)) (δ term G1 t1)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)

precompose (δ term G2) ∘ (ap G2 ∘ (map (Ap (A:=A)) ∘ δ term G2)) = compose (δ term G2) ∘ Ap (A:=G2 A)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)
s1, s2: term (G2 A)

(precompose (δ term G2) ∘ (ap G2 ∘ (map (Ap (A:=A)) ∘ δ term G2))) s1 s2 = (compose (δ term G2) ∘ Ap (A:=G2 A)) s1 s2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)
s1, s2: term (G2 A)

precompose (δ term G2) (ap G2 (map (Ap (A:=A)) (δ term G2 s1))) s2 = pure (Ap (A:=A)) <⋆> δ term G2 s1 <⋆> δ term G2 s2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1: Type -> Type
Map_G0: Map G1
Pure_G0: Pure G1
Mult_G0: Mult G1
H0: Applicative G1
G2: Type -> Type
Map_G1: Map G2
Pure_G1: Pure G2
Mult_G1: Mult G2
H1: Applicative G2
A: Type
t1, t2: term (G1 (G2 A))
IHt1: δ term (G1 ○ G2) t1 = map (δ term G2) (δ term G1 t1)
IHt2: δ term (G1 ○ G2) t2 = map (δ term G2) (δ term G1 t2)
s1, s2: term (G2 A)

map (Ap (A:=A)) (δ term G2 s1) <⋆> δ term G2 s2 = pure (Ap (A:=A)) <⋆> δ term G2 s1 <⋆> δ term G2 s2
now rewrite (map_to_ap). Qed. #[local] Unset Keyed Unification.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (G1 G2 : Type -> Type) (H0 : Map G1) (H1 : Mult G1) (H2 : Pure G1) (H3 : Map G2) (H4 : Mult G2) (H5 : Pure G2) (ϕ : forall A : Type, G1 A -> G2 A), ApplicativeMorphism G1 G2 ϕ -> forall A : Type, δ term G2 ∘ map (ϕ A) = ϕ (term A) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall (G1 G2 : Type -> Type) (H0 : Map G1) (H1 : Mult G1) (H2 : Pure G1) (H3 : Map G2) (H4 : Mult G2) (H5 : Pure G2) (ϕ : forall A : Type, G1 A -> G2 A), ApplicativeMorphism G1 G2 ϕ -> forall A : Type, δ term G2 ∘ map (ϕ A) = ϕ (term A) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type

δ term G2 ∘ map (ϕ A) = ϕ (term A) ∘ δ term G1
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t: term (G1 A)

(δ term G2 ∘ map (ϕ A)) t = (ϕ (term A) ∘ δ term G1) t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t: term (G1 A)

δ term G2 (map (ϕ A) t) = ϕ (term A) (δ term G1 t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
a: G1 A

δ term G2 (map (ϕ A) (Var a)) = ϕ (term A) (δ term G1 (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
X: typ
t: term (G1 A)
IHt: δ term G2 (map (ϕ A) t) = ϕ (term A) (δ term G1 t)
δ term G2 (map (ϕ A) (λ X ⋅ t)) = ϕ (term A) (δ term G1 (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
δ term G2 (map (ϕ A) ([t1][t2])) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
a: G1 A

δ term G2 (map (ϕ A) (Var a)) = ϕ (term A) (δ term G1 (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
a: G1 A

map (Var (A:=A)) (ϕ A a) = ϕ (term A) (map (Var (A:=A)) a)
now rewrite <- (appmor_natural).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
X: typ
t: term (G1 A)
IHt: δ term G2 (map (ϕ A) t) = ϕ (term A) (δ term G1 t)

δ term G2 (map (ϕ A) (λ X ⋅ t)) = ϕ (term A) (δ term G1 (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
X: typ
t: term (G1 A)
IHt: δ term G2 (map (ϕ A) t) = ϕ (term A) (δ term G1 t)

map (Lam X) (δ term G2 (map (ϕ A) t)) = ϕ (term A) (map (Lam X) (δ term G1 t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
X: typ
t: term (G1 A)
IHt: δ term G2 (map (ϕ A) t) = ϕ (term A) (δ term G1 t)

map (Lam X) (ϕ (term A) (δ term G1 t)) = ϕ (term A) (map (Lam X) (δ term G1 t))
now rewrite (appmor_natural).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)

δ term G2 (map (ϕ A) ([t1][t2])) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)

δ term G2 ([map (ϕ A) t1][map (ϕ A) t2]) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

δ term G2 ([map (ϕ A) t1][map (ϕ A) t2]) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (δ term G2 (map (ϕ A) t1)) <⋆> δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (ϕ (term A) (δ term G1 t1)) <⋆> δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (ϕ (term A) (δ term G1 t1)) <⋆> ϕ (term A) (δ term G1 t2) = ϕ (term A) (δ term G1 ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (ϕ (term A) (δ term G1 t1)) <⋆> ϕ (term A) (δ term G1 t2) = ϕ (term A) (map (Ap (A:=A)) (δ term G1 t1) <⋆> δ term G1 t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (ϕ (term A) (δ term G1 t1)) <⋆> ϕ (term A) (δ term G1 t2) = ϕ (term A -> term A) (map (Ap (A:=A)) (δ term G1 t1)) <⋆> ϕ (term A) (δ term G1 t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
G1, G2: Type -> Type
H0: Map G1
H1: Mult G1
H2: Pure G1
H3: Map G2
H4: Mult G2
H5: Pure G2
ϕ: forall A : Type, G1 A -> G2 A
H6: ApplicativeMorphism G1 G2 ϕ
A: Type
t1, t2: term (G1 A)
IHt1: δ term G2 (map (ϕ A) t1) = ϕ (term A) (δ term G1 t1)
IHt2: δ term G2 (map (ϕ A) t2) = ϕ (term A) (δ term G1 t2)
app1: Applicative G1
app2: Applicative G2

map (Ap (A:=A)) (ϕ (term A) (δ term G1 t1)) = ϕ (term A -> term A) (map (Ap (A:=A)) (δ term G1 t1))
now rewrite <- (appmor_natural). Qed. End dist_term_properties. #[export] Instance TraversableFunctor_term: TraversableFunctor term := {| dist_natural := @dist_Natural_term; dist_morph := @dist_morph_term; dist_linear := @dist_linear_term; dist_unit := @dist_unit_term; |}.

Decorated-Traversable Functor instance


forall (G : Type -> Type) (Map_G : Map G) (Pure_G : Pure G) (Mult_G : Mult G), Applicative G -> forall (X : typ) (A : Type), map (dec term ∘ Lam X) ∘ δ term G = map (curry (shift term) 1 ∘ Lam X) ∘ map (dec term) ∘ δ term G

forall (G : Type -> Type) (Map_G : Map G) (Pure_G : Pure G) (Mult_G : Mult G), Applicative G -> forall (X : typ) (A : Type), map (dec term ∘ Lam X) ∘ δ term G = map (curry (shift term) 1 ∘ Lam X) ∘ map (dec term) ∘ δ term G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
X: typ
A: Type

map (dec term ∘ Lam X) ∘ δ term G = map (curry (shift term) 1 ∘ Lam X) ∘ map (dec term) ∘ δ term G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
X: typ
A: Type

map (dec term ∘ Lam X) ∘ δ term G = map (curry (shift term) 1 ∘ Lam X ∘ dec term) ∘ δ term G
reflexivity. Qed.

forall (G : Type -> Type) (Map_G : Map G) (Pure_G : Pure G) (Mult_G : Mult G), Applicative G -> forall A : Type, δ term G ∘ map (σ) ∘ dec term = map (dec term) ∘ δ term G

forall (G : Type -> Type) (Map_G : Map G) (Pure_G : Pure G) (Mult_G : Mult G), Applicative G -> forall A : Type, δ term G ∘ map (σ) ∘ dec term = map (dec term) ∘ δ term G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

δ term G ∘ map (σ) ∘ dec term = map (dec term) ∘ δ term G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t: term (G A)

(δ term G ∘ map (σ) ∘ dec term) t = (map (dec term) ∘ δ term G) t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t: term (G A)

δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: G A

δ term G (map (σ) (dec term (Var a))) = map (dec term) (δ term G (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)
δ term G (map (σ) (dec term (λ X ⋅ t))) = map (dec term) (δ term G (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)
δ term G (map (σ) (dec term ([t1][t2]))) = map (dec term) (δ term G ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: G A

δ term G (map (σ) (dec term (Var a))) = map (dec term) (δ term G (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: G A

map (Var (A:=nat * A)) (map (pair Ƶ) a) = map (dec term) (map (Var (A:=A)) a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: G A

(map (Var (A:=nat * A)) ∘ map (pair Ƶ)) a = (map (dec term) ∘ map (Var (A:=A))) a
now rewrite 2(fun_map_map).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

δ term G (map (σ) (dec term (λ X ⋅ t))) = map (dec term) (δ term G (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (σ) (map (uncurry incr) (map (pair 1) (dec term t))))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (σ ∘ (uncurry incr ∘ pair 1)) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (σ ∘ uncurry incr ∘ pair 1) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (σ ∘ join ∘ pair 1) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (map (join ∘ pair 1) ∘ σ) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (map (join ○ pair 1)) (map (σ) (dec term t)))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (δ term G (map (join ○ pair 1) (map (σ) (dec term t)))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) ((δ term G ∘ map (join ○ pair 1)) (map (σ) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) ((δ term G ∘ map (join ○ pair 1)) (map (σ) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) ((map (join ○ pair 1) ∘ δ term G) (map (σ) (dec term t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (map (join ○ pair 1) (δ term G (map (σ) (dec term t)))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) (map (join ○ pair 1) (map (dec term) (δ term G t))) = map (dec term) (map (Lam X) (δ term G t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) ((map (join ○ pair 1) ∘ map (dec term)) (δ term G t)) = (map (dec term) ∘ map (Lam X)) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X) ((map (join ○ pair 1) ∘ map (dec term)) (δ term G t)) = map (dec term ∘ Lam X) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

(map (Lam X) ∘ (map (join ○ pair 1) ∘ map (dec term))) (δ term G t) = map (dec term ∘ Lam X) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

map (Lam X ∘ (map (join ○ pair 1) ∘ dec term)) (δ term G t) = map (dec term ∘ Lam X) (δ term G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)

Lam X ∘ (map (join ○ pair 1) ∘ dec term) = dec term ∘ Lam X
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)
t': term A

λ X ⋅ map (join ○ pair 1) (dec term t') = λ X ⋅ map (uncurry incr) (map (pair 1) (dec term t'))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)
t': term A

λ X ⋅ map (join ○ pair 1) (dec term t') = λ X ⋅ (map (uncurry incr) ∘ map (pair 1)) (dec term t')
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (G A)
IHt: δ term G (map (σ) (dec term t)) = map (dec term) (δ term G t)
t': term A

λ X ⋅ map (join ○ pair 1) (dec term t') = λ X ⋅ map (uncurry incr ∘ pair 1) (dec term t')
now rewrite incr_spec.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

δ term G (map (σ) (dec term ([t1][t2]))) = map (dec term) (δ term G ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

pure (Ap (A:=nat * A)) <⋆> δ term G (map (σ) (dec term t1)) <⋆> δ term G (map (σ) (dec term t2)) = map (dec term) (pure (Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

pure (Ap (A:=nat * A)) <⋆> map (dec term) (δ term G t1) <⋆> map (dec term) (δ term G t2) = map (dec term) (pure (Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

pure (Ap (A:=nat * A)) <⋆> map (dec term) (δ term G t1) <⋆> map (dec term) (δ term G t2) = map (compose (dec term)) (pure (Ap (A:=A)) <⋆> δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

pure (Ap (A:=nat * A)) <⋆> map (dec term) (δ term G t1) <⋆> map (dec term) (δ term G t2) = map (compose (compose (dec term))) (pure (Ap (A:=A))) <⋆> δ term G t1 <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

map (Ap (A:=nat * A) ∘ dec term) (δ term G t1) <⋆> map (dec term) (δ term G t2) = map (compose (compose (dec term))) (pure (Ap (A:=A))) <⋆> δ term G t1 <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

map (precompose (dec term)) (map (Ap (A:=nat * A) ∘ dec term) (δ term G t1)) <⋆> δ term G t2 = map (compose (compose (dec term))) (pure (Ap (A:=A))) <⋆> δ term G t1 <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

map (precompose (dec term)) (map (Ap (A:=nat * A) ∘ dec term) (δ term G t1)) <⋆> δ term G t2 = pure (compose (dec term) ∘ Ap (A:=A)) <⋆> δ term G t1 <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

map (precompose (dec term)) (map (Ap (A:=nat * A) ∘ dec term) (δ term G t1)) <⋆> δ term G t2 = map (compose (dec term) ∘ Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

(map (precompose (dec term)) ∘ map (Ap (A:=nat * A) ∘ dec term)) (δ term G t1) <⋆> δ term G t2 = map (compose (dec term) ∘ Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (G A)
IHt1: δ term G (map (σ) (dec term t1)) = map (dec term) (δ term G t1)
IHt2: δ term G (map (σ) (dec term t2)) = map (dec term) (δ term G t2)

map (precompose (dec term) ∘ (Ap (A:=nat * A) ∘ dec term)) (δ term G t1) <⋆> δ term G t2 = map (compose (dec term) ∘ Ap (A:=A)) (δ term G t1) <⋆> δ term G t2
reflexivity. Qed. #[export] Instance: DecoratedTraversableFunctor nat term := {| dtfun_compat := @dtfun_compat_term |}.

Monad instances

Plain Monad instance

Fixpoint join_term {A: Type} (t: term (term A)): term A :=
  match t with
  | Var t' => t'
  | Lam X t => Lam X (join_term t)
  | Ap t1 t2 => Ap (join_term t1) (join_term t2)
  end.

#[export] Instance Ret_term: Return term := @Var.

#[export] Instance Join_term: Join term := @join_term.


forall (A B : Type) (f : A -> B), map f ∘ ret = ret ∘ f

forall (A B : Type) (f : A -> B), map f ∘ ret = ret ∘ f
reflexivity. Qed.

forall (A B : Type) (f : A -> B), map f ∘ join = join ∘ map (map f)

forall (A B : Type) (f : A -> B), map f ∘ join = join ∘ map (map f)
A, B: Type
f: A -> B

map f ∘ join = join ∘ map (map f)
A, B: Type
f: A -> B
t: (term ∘ term) A

(map f ∘ join) t = (join ∘ map (map f)) t
A, B: Type
f: A -> B
t: (term ∘ term) A

(map_term f ∘ join_term) t = (join_term ∘ map_term (map_term f)) t
A, B: Type
f: A -> B
t: (term ∘ term) A

map_term f (join_term t) = join_term (map_term (map_term f) t)
basic t. Qed.

Natural (@ret term Ret_term)

Natural (@ret term Ret_term)

forall (A B : Type) (f : A -> B), map f ∘ ret = ret ∘ map f
apply ret_natural. Qed.

Natural (@join term Join_term)

Natural (@join term Join_term)

Functor (term ∘ term)

Functor term

forall (A B : Type) (f : A -> B), map f ∘ join = join ∘ map f

Functor (term ∘ term)
typeclasses eauto.

Functor term
typeclasses eauto.

forall (A B : Type) (f : A -> B), map f ∘ join = join ∘ map f
apply join_natural. Qed.

forall A : Type, join ∘ ret = id

forall A : Type, join ∘ ret = id
reflexivity. Qed.

forall A : Type, join ∘ map ret = id

forall A : Type, join ∘ map ret = id
A: Type

join ∘ map ret = id
A: Type

join ○ map ret = id
A: Type

join_term ○ map_term (Var (A:=A)) = id
A: Type
t: term A

join_term (map_term (Var (A:=A)) t) = id t
basic t. Qed.

forall A : Type, join ∘ join = join ∘ map join

forall A : Type, join ∘ join = join ∘ map join
A: Type

join ∘ join = join ∘ map join
A: Type

join ○ join = join ○ map join
A: Type

join_term ○ join_term = join_term ○ map_term join_term
A: Type
t: term (term (term A))

join_term (join_term t) = join_term (map_term join_term t)
basic t. Qed. #[export] Instance Monad_term: Monad term := {| mon_join_ret := join_ret; mon_join_map_ret := join_map_ret; mon_join_join := join_join |}.

Decorated Monad instance


forall A : Type, dec term ∘ ret = ret ∘ pair Ƶ

forall A : Type, dec term ∘ ret = ret ∘ pair Ƶ
reflexivity. Qed.

forall A : Type, dec term ∘ join = join ∘ map (shift term) ∘ dec term ∘ map (dec term)

forall A : Type, dec term ∘ join = join ∘ map (shift term) ∘ dec term ∘ map (dec term)
A: Type

dec term ∘ join = join ∘ map (shift term) ∘ dec term ∘ map (dec term)
A: Type

dec term ○ join = (fun a : term (term A) => join (map (shift term) (dec term (map (dec term) a))))
A: Type
t: term (term A)

dec term (join t) = join (map (shift term) (dec term (map (dec term) t)))
A: Type
a: term A

dec term (join (Var a)) = join (map (shift term) (dec term (map (dec term) (Var a))))
A: Type
X: typ
t: term (term A)
IHt: dec term (join t) = join (map (shift term) (dec term (map (dec term) t)))
dec term (join (λ X ⋅ t)) = join (map (shift term) (dec term (map (dec term) (λ X ⋅ t))))
A: Type
t1, t2: term (term A)
IHt1: dec term (join t1) = join (map (shift term) (dec term (map (dec term) t1)))
IHt2: dec term (join t2) = join (map (shift term) (dec term (map (dec term) t2)))
dec term (join ([t1][t2])) = join (map (shift term) (dec term (map (dec term) ([t1][t2]))))
A: Type
a: term A

dec term (join (Var a)) = join (map (shift term) (dec term (map (dec term) (Var a))))
A: Type
a: term A

dec term a = shift term (Ƶ, dec term a)
now rewrite (shift_zero term).
A: Type
X: typ
t: term (term A)
IHt: dec term (join t) = join (map (shift term) (dec term (map (dec term) t)))

dec term (join (λ X ⋅ t)) = join (map (shift term) (dec term (map (dec term) (λ X ⋅ t))))
A: Type
X: typ
t: term (term A)
IHt: dec term (join t) = join (map (shift term) (dec term (map (dec term) t)))

λ X ⋅ shift term (1, dec term (join t)) = λ X ⋅ join (map (shift term) (shift term (1, dec term (map (dec term) t))))
A: Type
X: typ
t: term (term A)
IHt: dec term (join t) = join (map (shift term) (dec term (map (dec term) t)))

shift term (1, dec term (join t)) = join (map (shift term) (shift term (1, dec term (map (dec term) t))))
now rewrite (dec_helper_4).
A: Type
t1, t2: term (term A)
IHt1: dec term (join t1) = join (map (shift term) (dec term (map (dec term) t1)))
IHt2: dec term (join t2) = join (map (shift term) (dec term (map (dec term) t2)))

dec term (join ([t1][t2])) = join (map (shift term) (dec term (map (dec term) ([t1][t2]))))
A: Type
t1, t2: term (term A)
IHt1: dec term (join t1) = join (map (shift term) (dec term (map (dec term) t1)))
IHt2: dec term (join t2) = join (map (shift term) (dec term (map (dec term) t2)))

[dec term (join t1)][dec term (join t2)] = [join (map (shift term) (dec term (map (dec term) t1)))] [join (map (shift term) (dec term (map (dec term) t2)))]
fequal; auto. Qed.

DecoratedMonad nat term

DecoratedMonad nat term

DecoratedFunctor nat term

Monad term

Monoid nat

forall A : Type, dec term ∘ ret = ret ∘ pair Ƶ

forall A : Type, dec term ∘ join = join ∘ map (shift term) ∘ dec term ∘ map (dec term)

DecoratedFunctor nat term
typeclasses eauto.

Monad term
typeclasses eauto.

Monoid nat
typeclasses eauto.

forall A : Type, dec term ∘ ret = ret ∘ pair Ƶ
apply dec_ret.

forall A : Type, dec term ∘ join = join ∘ map (shift term) ∘ dec term ∘ map (dec term)
apply dec_join. Qed.

Traversable Monad instance

G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term G ∘ ret = map ret
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term G ∘ ret = map ret
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

δ term G ∘ ret = map ret
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
x: G A

(δ term G ∘ ret) x = map ret x
reflexivity. Qed. From Tealeaves Require Import Categories.TraversableFunctor. #[local] Set Keyed Unification.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term G ∘ join = map join ∘ δ (term ∘ term) G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G

forall A : Type, δ term G ∘ join = map join ∘ δ (term ∘ term) G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type

δ term G ∘ join = map join ∘ δ (term ∘ term) G
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t: (term ∘ term) (G A)

(δ term G ∘ join) t = (map join ∘ δ (term ∘ term) G) t
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t: (term ∘ term) (G A)

δ term G (join t) = map join (δ (term ○ term) G t)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G (join (Var a)) = map join (δ (term ○ term) G (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)
δ term G (join (λ X ⋅ t)) = map join (δ (term ○ term) G (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)
δ term G (join ([t1][t2])) = map join (δ (term ○ term) G ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G (join (Var a)) = map join (δ (term ○ term) G (Var a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G a = map join (map (Var (A:=term A)) (δ term G a))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G a = (map join ∘ map (Var (A:=term A))) (δ term G a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G a = map (join ∘ Var (A:=term A)) (δ term G a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

δ term G a = map id (δ term G a)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)
id = join ∘ Var (A:=term A)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
a: term (G A)

id = join ∘ Var (A:=term A)
apply (join_ret).
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

δ term G (join (λ X ⋅ t)) = map join (δ (term ○ term) G (λ X ⋅ t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X) (δ term G (join t)) = map join (map (Lam X) (δ term G (map (δ term G) t)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X) (map join (δ (term ○ term) G t)) = map join (map (Lam X) (δ term G (map (δ term G) t)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X) (map join ((δ term G ∘ map (δ term G)) t)) = map join (map (Lam X) (δ term G (map (δ term G) t)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X) (map join (δ term G (map (δ term G) t))) = map join (map (Lam X) (δ term G (map (δ term G) t)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

(map (Lam X) ∘ map join) (δ term G (map (δ term G) t)) = (map join ∘ map (Lam X)) (δ term G (map (δ term G) t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X ∘ join) (δ term G (map (δ term G) t)) = (map join ∘ map (Lam X)) (δ term G (map (δ term G) t))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
X: typ
t: term (term (G A))
IHt: δ term G (join t) = map join (δ (term ○ term) G t)

map (Lam X ∘ join) (δ term G (map (δ term G) t)) = map (join ∘ Lam X) (δ term G (map (δ term G) t))
reflexivity.
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

δ term G (join ([t1][t2])) = map join (δ (term ○ term) G ([t1][t2]))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

pure (Ap (A:=A)) <⋆> δ term G (join t1) <⋆> δ term G (join t2) = map join (pure (Ap (A:=term A)) <⋆> δ term G (map (δ term G) t1) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

pure (Ap (A:=A)) <⋆> map join (δ (term ○ term) G t1) <⋆> map join (δ (term ○ term) G t2) = map join (pure (Ap (A:=term A)) <⋆> δ term G (map (δ term G) t1) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

pure (Ap (A:=A)) <⋆> map join ((δ term G ∘ map (δ term G)) t1) <⋆> map join ((δ term G ∘ map (δ term G)) t2) = map join (pure (Ap (A:=term A)) <⋆> δ term G (map (δ term G) t1) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

pure (Ap (A:=A)) <⋆> map join (δ term G (map (δ term G) t1)) <⋆> map join (δ term G (map (δ term G) t2)) = map join (pure (Ap (A:=term A)) <⋆> δ term G (map (δ term G) t1) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (Ap (A:=A)) (map join (δ term G (map (δ term G) t1))) <⋆> map join (δ term G (map (δ term G) t2)) = map join (pure (Ap (A:=term A)) <⋆> δ term G (map (δ term G) t1) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (Ap (A:=A)) (map join (δ term G (map (δ term G) t1))) <⋆> map join (δ term G (map (δ term G) t2)) = map join (map (Ap (A:=term A)) (δ term G (map (δ term G) t1)) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join) (map (Ap (A:=A)) (map join (δ term G (map (δ term G) t1)))) <⋆> δ term G (map (δ term G) t2) = map join (map (Ap (A:=term A)) (δ term G (map (δ term G) t1)) <⋆> δ term G (map (δ term G) t2))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join) (map (Ap (A:=A)) (map join (δ term G (map (δ term G) t1)))) <⋆> δ term G (map (δ term G) t2) = map (compose join) (map (Ap (A:=term A)) (δ term G (map (δ term G) t1))) <⋆> δ term G (map (δ term G) t2)
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join) (map (Ap (A:=A)) (map join (δ term G (map (δ term G) t1)))) = map (compose join) (map (Ap (A:=term A)) (δ term G (map (δ term G) t1)))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join) ((map (Ap (A:=A)) ∘ map join) (δ term G (map (δ term G) t1))) = (map (compose join) ∘ map (Ap (A:=term A))) (δ term G (map (δ term G) t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join) (map (Ap (A:=A) ∘ join) (δ term G (map (δ term G) t1))) = map (compose join ∘ Ap (A:=term A)) (δ term G (map (δ term G) t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

(map (precompose join) ∘ map (Ap (A:=A) ∘ join)) (δ term G (map (δ term G) t1)) = map (compose join ∘ Ap (A:=term A)) (δ term G (map (δ term G) t1))
G: Type -> Type
Map_G: Map G
Pure_G: Pure G
Mult_G: Mult G
H: Applicative G
A: Type
t1, t2: term (term (G A))
IHt1: δ term G (join t1) = map join (δ (term ○ term) G t1)
IHt2: δ term G (join t2) = map join (δ (term ○ term) G t2)

map (precompose join ∘ (Ap (A:=A) ∘ join)) (δ term G (map (δ term G) t1)) = map (compose join ∘ Ap (A:=term A)) (δ term G (map (δ term G) t1))
fequal. Qed. #[local] Set Keyed Unification. #[export] Instance TraversableMonad_term: TraversableMonad term := {| trvmon_ret := @trvmon_ret_term; trvmon_join := @trvmon_join_term; |}.

Decorated-Traversable Monad instance

Our hard work has paid off---a DTM is defined as the combination of the typeclass instances we have given so far, so we can let Coq infer the DTM instance for us.

#[export] Instance DTM_STLC: DecoratedTraversableMonad nat term := {}.