Library HoTT.Categories.ExponentialLaws.Tactics

Miscellaneous helper tactics for proving exponential laws

These are probably more general than just exponential laws, but I haven't tried them more widely, yet.
Miscellaneous tactics to try
Ltac exp_laws_misc_t' :=
  idtac;
  match goal with
    | _reflexivity
    | _progress intros
    | _progress simpl in ×
    | _apply (@path_forall _); intro
    | _rewrite !identity_of
    | _progress autorewrite with morphism
  end.

Safe transformations to simplify complex types in the hypotheses or goal
Ltac exp_laws_simplify_types' :=
  idtac;
  match goal with
    | [ H : (_ + _) |- _ ] ⇒ destruct H
    | [ H : Unit |- _ ] ⇒ destruct H
    | [ H : Empty |- _ ] ⇒ destruct H
    | [ H : (_ × _) |- _ ] ⇒ destruct H
    | [ |- _ = _ :> Functor _ _ ] ⇒ progress path_functor
    | [ |- _ = _ :> NaturalTransformation _ _ ] ⇒ progress path_natural_transformation
    | [ |- _ = _ :> prod _ _ ] ⇒ apply path_prod
  end.

Do some simplifications of contractible types
Ltac exp_laws_handle_contr' :=
  idtac;
  match goal with
    | [ H : Contr ?T, x : ?T |- _ ] ⇒ progress destruct (contr x)
    | [ H : a, Contr (?T a), x : ?T _ |- _ ] ⇒ progress destruct (contr x)
    | [ H : a b, Contr (?T a b), x : ?T _ _ |- _ ] ⇒ progress destruct (contr x)
    | [ |- context[contr (center ?x)] ]
      ⇒ progress let H := fresh in
                  assert (H : idpath = contr (center x)) by exact (center _);
                    destruct H
  end.

Try to simplify transport with some heuristics
Ltac exp_laws_handle_transport' :=
  idtac;
  match goal with
    | _progress rewrite ?transport_forall_constant, ?path_forall_2_beta, ?transport_const, ?transport_path_prod
    | [ |- context [path_functor_uncurried ?F ?G (?x; ?y)] ] (* https://coq.inria.fr/bugs/show_bug.cgi?id=3768 *)
      ⇒ rewrite (@path_functor_uncurried_fst _ _ _ F G x y)
    | [ |- context[transport (fun y : Functor ?C ?D ⇒ ?f (y _0 ?x)%object)] ]
      ⇒ rewrite (fun a b ⇒ @transport_compose _ _ a b (fun y'f (y' x)) (@object_of C D))
    | [ |- context[transport (fun y : Functor ?C ?D ⇒ ?f (y _0 ?x)%object ?z)] ]
      ⇒ rewrite (fun a b ⇒ @transport_compose _ _ a b (fun y'f (y' x) z) (@object_of C D))
    | [ |- context[transport (fun y : Functor ?C ?D ⇒ ?f (y _0 ?x)%object ?z)] ]
      ⇒ rewrite (fun a b ⇒ @transport_compose _ _ a b (fun y'f (y' x) z) (@object_of C D))
    | [ |- context[transport (fun y : Functor ?C ?D ⇒ ?f (?g (y _0 ?x)%object))] ]
      ⇒ rewrite (fun a b ⇒ @transport_compose _ _ a b (fun y'f (g (y' x))) (@object_of C D))
    | [ |- context[transport (fun y : Functor ?C ?D ⇒ ?f (?g (y _0 ?x)%object) ?z)] ]
      ⇒ rewrite (fun a b ⇒ @transport_compose _ _ a b (fun y'f (g (y' x)) z) (@object_of C D))
    | _progress transport_path_forall_hammer
    | [ |- context[components_of (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _components_of) z)
    | [ |- context[object_of (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _object_of) z)
    | [ |- context[morphism_of (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _morphism_of) z)
    | [ |- context[fst (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _fst) z)
    | [ |- context[snd (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _snd) z)
    | [ |- context[pr1 (transport ?P ?p ?z)] ]
      ⇒ simpl rewrite (@ap_transport _ P _ _ _ p (fun _pr1) z)
  end.

Ltac exp_laws_t' :=
  first [ exp_laws_misc_t'
        | exp_laws_simplify_types'
        | exp_laws_handle_contr'
        | exp_laws_handle_transport' ].

Ltac exp_laws_t := repeat exp_laws_t'.