UniMath

This coq library aims to formalize a substantial body of mathematics using the univalent point of view.

View the Project on GitHub UniMath/UniMath

Transports

As mentioned before in the tutorial about paths, if we have a type X and a family of types Y : X → UU, and if we have a path p : x = x' for x x' : X, we can ‘transport’ a term y : Y x over this path to get transportf Y e y : Y x', or transport y' : Y x' to get transportb Y e y' : Y x (note that transportb Y e is defined as transportf Y (!e)). For example, if we have m n : nat, Hmn : m = n and Hm : m ≥ 5, and if our goal is n ≥ 5, transportf (λ l, l ≥ 5) Hmn Hm solves this goal. Note that using a transport instead of rewriting is usually not the right approach, even though it is a possibility.

Often when proving (x ,, y) = (x' ,, y') in a b : ∑ x, Y x, one will first show that H : x = x' and then that transportf Y H y = y'. However, the latter part can be really hard. In this tutorial, we will take a look at some ways to work with transports. We will take a look at

Avoiding transports

Often, the best approach of dealing with transports is to avoid them wherever possible. It is notoriously hard to navigate through ‘transport hell’, so there are some techniques to make sure you encounter them as little as possible. Most of them boil down to working in small steps:

Existing lemmas

If you have tried all of the above, but were unable to avoid transports, don’t panic. There are lemmas in the library which can help you reduce transports to a trivial case and eliminate them.

Now, most types in UniMath are parameterized: functions and morphisms have a domain and a codomain, natural transformations connect two functors, which in turn connect two categories, the type A[n] of A-lists of length n has both A and n as a parameter, etc. For many types and their parameters, there are lemmas about their behaviour under transports. For example:

Custom lemmas

Most of the time, lemmas such as those in the previous section suffice for the simple cases that you encounter once or twice. However, sometimes the dependent type Y is very complicated and sometimes you need a certain fact about transports multiple times.

If you need to reduce a transport to a statement without transports (for example, replacing the transport by a composition with idtoiso), it often helps to generalize the statement a bit, to make it work for transport over general paths H : x = x', and turn it into an auxiliary lemma. In this lemma, you can use induction to trivialize the transport and turn every idtoiso into the identity isomorphism. Then most of the time, the goal becomes a statement about how working with the identity does not change anything.

Consider a somewhat complicated example, where we work with pairs (X, Xdata), consisting of a category X and a D-presheaf Xdata on that category. Morphisms between such category-presheaf pairs are again a pair (f, fdata), consisting of a backwards functor f between the categories and a natural transformation fdata from the pullback f* Xdata to Ydata. The following lemma then states that transporting such a transformation fdata along a path e : f = g is the same as precomposing it with some whiskered version of idtoiso e:

Local Lemma aux1
  {D : category}
  {X Y : category}
  (f g : Y  X)
  (H : f = g)
  {Xdata : X^op  D}
  {Ydata : Y^op  D}
  (fdata : functor_opp f  Xdata  Ydata)
  : transportf (λ t, functor_opp t  Xdata  Ydata) H fdata
    = nat_trans_comp _ _ _ (post_whisker (op_nt (z_iso_mor (idtoiso (C := [_, _]) H))) Xdata) fdata.
Proof.
  (* Induction on H replaces g by f, makes the transport trivial and turns `z_iso_mor (idtoiso H)` into the identity natural transformation *)
  induction H.
  (* The goal is now `fdata = nat_trans_comp _ _ _ (post_whisker (op_nt (nat_trans_id f)) Xdata) fdata *)
  apply (nat_trans_eq_alt _ Ydata).
  (* nat_trans_eq_alt reduces a proof about natural transformations to a pointwise proof about the morphisms at every x *)
  intro x.
  (* The goal is now `fdata x = # (pr1 Xdata) (identity (pr1 f x)) · fdata x` *)
  refine (!id_left _ @ _).
  apply (maponpaths (λ x, x · _)).
  now refine (!functor_id Xdata _ @ _).
Qed.