Tealeaves.Classes.Kleisli.TraversableFunctor

From Tealeaves Require Export
  Classes.Categorical.Applicative.

#[local] Generalizable Variables T G A B C ϕ M.

Traversable Functors

Operation traverse

Class Traverse (T: Type Type) :=
  traverse:
     (G: Type Type)
      `{Map_G: Map G} `{Pure_G: Pure G} `{Mult_G: Mult G}
      (A B: Type), (A G B) T A G (T B).

#[global] Arguments traverse {T}%function_scope {Traverse}
  {G}%function_scope
  {Map_G Pure_G Mult_G}
  {A B}%type_scope _%function_scope _.

Kleisli Composition

Definition kc2
  {G1 G2: Type Type}
  `{Map_G1: Map G1}
  {A B C: Type}:
  (B G2 C)
  (A G1 B)
  (A (G1 G2) C) :=
  fun g fmap (F := G1) (A := B) (B := G2 C) g f.

#[local] Infix "⋆2" := (kc2) (at level 60): tealeaves_scope.

Typeclass

Class TraversableFunctor (T: Type Type)
  `{Traverse_T: Traverse T} :=
  { trf_traverse_id: (A: Type),
      traverse (G := fun AA) id = @id (T A);
    trf_traverse_traverse:
     `{Applicative G1} `{Applicative G2}
      (A B C: Type) (g: B G2 C) (f: A G1 B),
      map (traverse g) traverse f =
        traverse (T := T) (G := G1 G2) (g ⋆2 f);
    trf_traverse_morphism:
     `{morphism: ApplicativeMorphism G1 G2 ϕ}
      (A B: Type) (f: A G1 B),
      ϕ (T B) traverse f = traverse (ϕ B f);
  }.

Kleisli Composition Laws

TODO

Traversable Functor Homomorphisms

Class TraversableMorphism
  (T U: Type Type)
  `{Traverse_T: Traverse T}
  `{Traverse_U: Traverse U}
  (ϕ: (A: Type), T A U A) :=
  { trvmon_hom:
     `{Applicative G} `(f: A G B),
      map (F := G) (ϕ B) traverse (T := T) (G := G) f =
        traverse (T := U) (G := G) f ϕ A;
  }.

Derived Structures

Derived map Operation

Module DerivedOperations.

  #[export] Instance Map_Traverse (T: Type Type)
    `{Traverse_T: Traverse T}: Map T :=
  fun (A B: Type) (f: A B) ⇒ traverse (G := fun AA) f.

End DerivedOperations.

Class Compat_Map_Traverse T
  `{Map_T: Map T}
  `{Traverse_T: Traverse T}: Prop :=
  compat_map_traverse:
    Map_T = @DerivedOperations.Map_Traverse T Traverse_T.

#[export] Instance Compat_Map_Traverse_TraversableFunctor
  `{Traverse_T: Traverse T}:
  Compat_Map_Traverse T
    (Map_T := DerivedOperations.Map_Traverse T).
Proof.
  reflexivity.
Qed.

Corollary map_to_traverse
  `{Compat_Map_Traverse T}: `(f: A B),
    map (F := T) f = traverse (G := fun AA) f.
Proof.
  rewrite compat_map_traverse.
  reflexivity.
Qed.

Composition with the Identity Applicative

Section properties.

  Context
    `{TraversableFunctor T}.

***Left identity law
  Lemma traverse_app_id_l {A B: Type} `{Applicative G}:
     (f: A G B),
      @traverse T _ ((fun AA) G) (Map_compose (fun AA) G)
        (Pure_compose (fun AA) G) (Mult_compose (fun AA) G) A B f
      = traverse f.
  Proof.
    intros. fequal.
    now rewrite (Mult_compose_identity2 G).
  Qed.

Right identity law

  Lemma traverse_app_id_r {A B: Type} `{Applicative G}:
     (f: A G B),
      @traverse T _ (G (fun AA)) (Map_compose G (fun AA))
        (Pure_compose G (fun AA)) (Mult_compose G (fun AA)) A B f
      = traverse f.
  Proof.
    intros. fequal.
    now rewrite (Mult_compose_identity1 G).
  Qed.

End properties.

Derived Composition Laws

Section traversable_functor_derived_composition_laws.

  Context
    `{TraversableFunctor T}
    `{Map T}
    `{! Compat_Map_Traverse T }.

  Context
    {G1 G2: Type Type}
    `{Applicative G2}
    `{Applicative G1}.

Composition between traverse and map

  Lemma map_traverse {A B C: Type}: (g: B C) (f: A G1 B),
      map (F := G1) (A := T B) (B := T C) (map g) traverse f =
        traverse (map g f).
  Proof.
    intros.
    rewrite (map_to_traverse (T := T)).
    rewrite (trf_traverse_traverse (G2 := fun AA)).
    rewrite traverse_app_id_r.
    reflexivity.
  Qed.

  Lemma traverse_map {A B C: Type}: (g: B G2 C) (f: A B),
      traverse g map f = traverse (g f).
  Proof.
    intros.
    rewrite (map_to_traverse (T := T)).
    change (traverse g)
      with (map (F := fun AA) (traverse g)).
    rewrite (trf_traverse_traverse (G1 := fun AA)).
    rewrite traverse_app_id_l.
    reflexivity.
  Qed.

Functor laws

  Lemma map_map: (A B C: Type) (f: A B) (g: B C),
      map g map f = map (F := T) (g f).
  Proof.
    intros.
    rewrite (map_to_traverse (T := T)).
    rewrite (map_to_traverse (T := T)).
    rewrite (map_to_traverse (T := T)).
    change (traverse (G := fun AA) g)
      with (map (F := fun AA) (traverse (G := fun AA) g)).
    rewrite (trf_traverse_traverse
               (G1 := fun AA) (G2 := fun AA)).
    rewrite traverse_app_id_l.
    reflexivity.
  Qed.

  Lemma map_id: (A: Type),
      map id = @id (T A).
  Proof.
    intros.
    rewrite map_to_traverse.
    rewrite trf_traverse_id.
    reflexivity.
  Qed.

End traversable_functor_derived_composition_laws.

Derived Typeclass Instances

Module DerivedInstances.

  #[export] Instance Functor_TraversableFunctor
    `{TraversableFunctor T}
    `{Map T}
    `{! Compat_Map_Traverse T}: Functor T :=
  {| fun_map_id := map_id;
     fun_map_map := map_map;
  |}.

End DerivedInstances.

Notations

Module Notations.
  Infix "⋆2" := (kc2) (at level 60): tealeaves_scope.
End Notations.