Built with Alectryon. 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.
From HoTT.Basics Require Import Overture Numeral Tactics Decidable.From HoTT.Basics Require Import Overture Numeral Tactics Decidable.From HoTT.Basics Require Import Equivalences PathGroupoids Trunc Iff.Require Import Types.Paths Types.Universe.Require Import Spaces.Nat.Core Spaces.SInt.(** Users of this file likely want the instances in Equiv.BiInv, such as [isequiv_isbiinv], so we export this file. *)Require Export Equiv.BiInv.(** * The integers, defined as a HIT *)(** Following "The integers as a higher inductive type" by Altenkirch and Scoccola, we define the integers as a higher inductive type. Morally it is the free pointed type with a biinvertible self-map. This representation leads to more convenient induction and recursion principles that avoid needing to split into many cases as happens with the signed integers [SInt]. Moreover, many results hold definitionally instead of requiring lengthy proofs. Examples include results about addition, multiplication, iteration of equivalences and exponentiation of loops such as [int_add_succ_l], [int_mul_pred_l], [int_iter_succ_l], and [loopexp_pred_r] to name just a few. We also have a convenient lemma [int_homotopic] for proving that two functions [Int -> P] are homotopic. Part of what makes it easy to use is that the functions being compared often compute definitionally on [zero] and [int_succ].One difference compared to the Altenkirch-Scoccola paper is that we prove additional induction principles, [int_ind_biinv] and [int_ind_equiv]. The key to these is a carefully chosen proof of [int_succ_pred] that satisfies the half-adjoint law. Then, using [int_ind_equiv], we are able to trivially prove [int_homotopic] (their Theorem 2.4) without using univalence or needing to introduce "prBiInv" (squares preserving bi-invertible maps). As a result, we don't need univalence for any fundamental results about the integers.One thing to be aware of is that the representation of integers is no longer definitionally unique. For example, [2 - 3] is not definitionally equal to [-1]. [int_reduce] or [ltac:(decide)] can be used to show that these are equal, with [int_reduce] being faster, as illustrated in test/Spaces/Int.v. *)Set Universe Minimization ToSet.Declare Scope int_scope.Delimit Scope int_scope with int.LocalOpen Scope int_scope.(** ** The definition of [Int] *)ModuleExport Int.SectionInt.(** Here we are modeling the HIT which has a point [zero] and a successor map [int_succ] which is a biinvertible equivalence. [int_pred] and [int_pred2] are its left and right inverses. *)Private InductiveInt : Type0 :=
| zero : Int
| int_succ : Int -> Int
| int_pred : Int -> Int
| int_pred2 : Int -> Int.Axiomint_pred_succ : int_pred o int_succ == idmap.Axiomint_succ_pred2 : int_succ o int_pred2 == idmap.Context {P : Int -> Type} (t0 : P zero) (e : forallz : Int, P z -> P (int_succ z))
(r : forallz : Int, P z -> P (int_pred z)) (s : forallz : Int, P z -> P (int_pred2 z))
(re : forall (z : Int) (t : P z), int_pred_succ z # (r (int_succ z) (e z t)) = t)
(es : forall (z : Int) (t : P z), int_succ_pred2 z # (e (int_pred2 z) (s z t)) = t).Fixpointint_ind (z : Int) : P z
:= match z with
| zero => fun__ => t0
| int_succ z => fun__ => e z (int_ind z)
| int_pred z => fun__ => r z (int_ind z)
| int_pred2 z => fun__ => s z (int_ind z)
end re es.(** We make sure that this depends on [re] and [es] as well. *)(** The beta principles for [int_ind] on [int_pred_succ] and [int_succ_pred2]. *)Axiomint_ind_beta_int_pred_succ
: forall (z : Int), apD int_ind (int_pred_succ z) = re z (int_ind z).Axiomint_ind_beta_int_succ_pred2
: forall (z : Int), apD int_ind (int_succ_pred2 z) = es z (int_ind z).EndInt.EndInt.(** We sometimes want to treat the integers as a pointed type with basepoint given by 0. *)Instanceispointed_int : IsPointed Int := zero.(** Successor is biinvertible. It follows from typeclass inference that it is an equivalence. *)Instanceisbiinv_int_succ : IsBiInv int_succ
:= Build_IsBiInv _ _ _ int_pred2 int_pred int_succ_pred2 int_pred_succ.Definitionbiinv_int_succ : BiInv Int Int
:= Build_BiInv _ _ int_succ _.(** The predecessor is an equivalence on [Int]. *)Instanceisequiv_int_pred : IsEquiv int_pred
:= isequiv_retr_biinv int_succ.Notation"z .+1" := (int_succ z) : int_scope.Notation"z .-1" := (int_pred z) : int_scope.(** [int_pred] is a section of [int_succ]. *)Definitionint_succ_pred : int_succ o int_pred == idmap
:= retr_is_sect_isbiinv int_succ.(** [int_pred2] is a retraction of [int_succ]. *)Definitionint_pred2_succ : int_pred2 o int_succ == idmap
:= sect_is_retr_isbiinv int_succ.(** Our proof of [retr_is_sect_isbiinv] was carefully chosen so that the data showing that [int_succ] and [int_pred] form an equivalence satisfies the adjoint law. *)Definitionint_succ_isadj (z : Int)
: int_succ_pred (int_succ z) = ap int_succ (int_pred_succ z)
:= eisadj int_succ z.(** ** Induction and recursion principles for Int *)
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z -> P z.-1
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z -> P (int_pred2 z)
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forall (z : Int) (t : P z),
transport P (int_pred_succ z) (?r z.+1 (e z t)) = t
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forall (z : Int) (t : P z),
transport P (int_succ_pred2 z) (e (int_pred2 z) (?s z t)) = t
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z -> P z.-1
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int
P z -> P z.-1
exact ((retr_biinv (e z.-1)) o transport P (int_succ_pred z)^).
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forallz : Int, P z -> P (int_pred2 z)
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int
P z -> P (int_pred2 z)
exact ((e (int_pred2 z))^-1 o transport P (int_succ_pred2 z)^).
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forall (z : Int) (t : P z),
transport P (int_pred_succ z)
((funz0 : Int => retr_biinv (e z0.-1) o transport P (int_succ_pred z0)^)
z.+1 (e z t)) =
t
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport P (int_pred_succ z)
(retr_biinv (e z.+1.-1) (transport P (int_succ_pred z.+1)^ (e z p))) =
p
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
retr_biinv (e z)
(transport (funz0 : Int => P z0.+1) (int_pred_succ z)
(transport P (int_succ_pred z.+1)^ (e z p))) =
p
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport (funz0 : Int => P z0.+1) (int_pred_succ z)
(transport P (int_succ_pred z.+1)^ (e z p)) =
?Goal
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
retr_biinv (e z) ?Goal = p
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport (funz0 : Int => P z0.+1) (int_pred_succ z)
(transport P (int_succ_pred z.+1)^ (e z p)) =
?Goal
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport P (ap int_succ (int_pred_succ z))
(transport P (int_succ_pred z.+1)^ (e z p)) =
?Goal
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport P ((int_succ_pred z.+1)^ @ ap int_succ (int_pred_succ z)) (e z p) =
?Goal
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
(int_succ_pred z.+1)^ @ ap int_succ (int_pred_succ z) = ?q
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
(ap int_succ (int_pred_succ z))^ @ ap int_succ (int_pred_succ z) = ?q
apply concat_Vp.
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
retr_biinv (e z) (transport P 1 (e z p)) = p
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
retr_biinv (e z) (e z p) = p
apply eissect_biinv.
P: Int -> Type t0: P zero e: forallz : Int, P z -> P z.+1 iseq: forallz : Int, IsBiInv (e z)
forall (z : Int) (t : P z),
transport P (int_succ_pred2 z)
(e (int_pred2 z)
((funz0 : Int =>
(e (int_pred2 z0))^-1 o transport P (int_succ_pred2 z0)^) z t)) =
t
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport P (int_succ_pred2 z)
(e (int_pred2 z) ((e (int_pred2 z))^-1 (transport P (int_succ_pred2 z)^ p))) =
p
P: Int -> Type t0: P zero e: forallz0 : Int, P z0 -> P z0.+1 iseq: forallz0 : Int, IsBiInv (e z0) z: Int p: P z
transport P (int_succ_pred2 z) (transport P (int_succ_pred2 z)^ p) = p
apply transport_pV.Defined.Definitionint_ind_equiv {P : Int -> Type} (t0 : P zero)
(e : forallz : Int, P z -> P z.+1) {iseq : forallz, IsEquiv (e z)}
: forallz, P z
:= @int_ind_biinv P t0 e (funz => isbiinv_isequiv _ (iseq z)).SectionRecursionPrinciple.Context {P : Type} (t0 : P) (f : P -> P) (g1g2 : P -> P)
(s : g1 o f == idmap) (r : f o g2 == idmap).(** The recursion principle. *)
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
Int -> P
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
Int -> P
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
forall (z : Int) (t : (fun_ : Int => P) z),
transport (fun_ : Int => P) (int_pred_succ z)
((fun_ : Int => g1) z.+1 ((fun_ : Int => f) z t)) =
t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
forall (z : Int) (t : (fun_ : Int => P) z),
transport (fun_ : Int => P) (int_succ_pred2 z)
((fun_ : Int => f) (int_pred2 z) ((fun_ : Int => g2) z t)) =
t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
transport (fun_ : Int => P) (int_pred_succ z) (g1 (f t)) = t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
transport (fun_ : Int => P) (int_succ_pred2 z) (f (g2 t)) = t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
g1 (f t) = t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
f (g2 t) = t
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
g1 (f t) = t
apply s.
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int t: (fun_ : Int => P) z
f (g2 t) = t
apply r.Defined.
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
forallz : Int, ap int_rec (int_pred_succ z) = s (int_rec z)
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap
forallz : Int, ap int_rec (int_pred_succ z) = s (int_rec z)
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int
ap int_rec (int_pred_succ z) = s (int_rec z)
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int
transport_const (int_pred_succ z) (int_rec z.+1.-1) @
ap int_rec (int_pred_succ z) =
transport_const (int_pred_succ z) (int_rec z.+1.-1) @ s (int_rec z)
P: Type t0: P f, g1, g2: P -> P s: g1 o f == idmap r: f o g2 == idmap z: Int
napply int_ind_beta_int_succ_pred2.Defined.EndRecursionPrinciple.(** The recursion principle phrased using a biinvertible map. *)Definitionint_rec_biinv {P : Type} (t0 : P) (f : P -> P) `{IsBiInv P P f}
: Int -> P
:= int_rec t0 f (retr_biinv f) (sect_biinv f) (eissect_biinv f) (eisretr_biinv f).(** The recursion principle phrased using a half-adjoint equivalence. *)Definitionint_rec_equiv {P : Type} (t0 : P) (f : P -> P) `{IsEquiv P P f}
: Int -> P
:= @int_rec_biinv P t0 f (isbiinv_isequiv _ _).(** Equivalence iteration. The properties of this are proved later in the file. *)Definitionint_iter {A} (f : A -> A) `{!IsEquiv f} (z : Int) (a0 : A) : A
:= int_rec_equiv a0 f z.SectionUniqueness.Context {P : Type} (e : BiInv P P).(** The following uniqueness principle states that if two maps out of [Int] agree on 0 and commute with the successor, then they are homotopic. *)
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
k1 == k2
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
k1 == k2
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
k1 zero = k2 zero
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
forallz : Int, k1 z = k2 z -> k1 z.+1 = k2 z.+1
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
forallz : Int, IsEquiv (?Goal0 z)
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
k1 zero = k2 zero
exact p0.
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
forallz : Int, k1 z = k2 z -> k1 z.+1 = k2 z.+1
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2 z: Int
P: Type e: BiInv P P k1, k2: Int -> P p0: k1 zero = k2 zero pf1: k1 o int_succ == e o k1 pf2: k2 o int_succ == e o k2
forallz : Int,
IsEquiv
((funz0 : Int =>
equiv_fun
(equiv_concat_l (pf1 z0) (k2 z0.+1)
oE equiv_concat_r (pf2 z0)^ (e (k1 z0)) oE
equiv_ap e (k1 z0) (k2 z0)))
z)
exact _.Defined.(** As a special case, we can characterize the recursor. *)Definitionint_homotopic_rec (t0 : P) (k : Int -> P)
(p0 : k zero = t0) (pf : k o int_succ == e o k)
(rec := int_rec_biinv t0 e)
: k == rec
:= int_homotopic_biinv k rec p0 pf (fun_ => idpath).EndUniqueness.(** The same uniqueness principle but for half-adjoint equivalences. *)Definitionint_homotopic {P : Type} (f : P -> P)
{e' : IsEquiv f} (k1 : Int -> P) (k2 : Int -> P)
(p0 : k1 zero = k2 zero) (pf1 : k1 o int_succ == f o k1)
(pf2 : k2 o int_succ == f o k2)
: forall (z : Int), k1 z = k2 z
:= int_homotopic_biinv (Build_BiInv P P _ (isbiinv_isequiv f e')) k1 k2 p0 pf1 pf2.(** ** [Int] is equivalent to [SInt] *)Definitionint_to_sint : Int -> SInt
:= int_rec sint_zero sint_succ sint_pred sint_pred sint_pred_succ sint_succ_pred.
apply sint_to_int_succ.Defined.(** [sint_to_int] is biinvertible. It follows from typeclass inference that it is an equivalence. *)Instanceisbiinv_sint_to_int : IsBiInv sint_to_int
:= Build_IsBiInv _ _ _ _ _ sint_to_int_isretr sint_to_int_issect.(** Since [SInt] has decidable equality, so does [Int]. *)Instancedecidablepaths_int@{} : DecidablePaths Int
:= decidablepaths_equiv SInt _ _.(** Since [SInt] is a set, therefore also [Int] is a set. *)Instanceishset_int : IsHSet Int
:= istrunc_isequiv_istrunc SInt _.(** The following function reduces an integer expression by cancelling successive successor and predecessor terms. It is homotopic to the identity by [sint_to_int_isretr]. *)Definitionint_reduce : Int -> Int := sint_to_int o int_to_sint.(** From the equivalence to [SInt] we can deduce another induction principle for [Int]. This one has weak hypotheses, but since [HN 1 (HP 0 t)] doesn't necessarily transport to [t] along [int_pred_succ 0], it is impossible for it to compute well on general [int_pred] and [int_succ] operations. Passing through [SInt] normalizes terms giving us a canonical choice. *)
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1
forallz : Int, P z
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1
forallz : Int, P z
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 s: SInt
P (sint_to_int s)
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1
P (sint_to_int sint_zero)
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_of_nat n))
P (sint_to_int (sint_PosS n))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_neg (sint_of_nat n)))
P (sint_to_int (sint_NegS n))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1
P (sint_to_int sint_zero)
exact H0.
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_of_nat n))
P (sint_to_int (sint_PosS n))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 IHz: P (sint_to_int (sint_of_nat 0))
P (sint_to_int (sint_PosS 0))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_of_nat n.+1))
P (sint_to_int (sint_PosS n.+1))
all: apply HP, IHz.
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_neg (sint_of_nat n)))
P (sint_to_int (sint_NegS n))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 IHz: P (sint_to_int (sint_neg (sint_of_nat 0)))
P (sint_to_int (sint_NegS 0))
P: Int -> Type H0: P zero HP: forallz : Int, P z -> P z.+1 HN: forallz : Int, P z -> P z.-1 n: nat IHz: P (sint_to_int (sint_neg (sint_of_nat n.+1)))
P (sint_to_int (sint_NegS n.+1))
all: apply HN, IHz.Defined.
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z -> P z.+1
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z -> P z.-1
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z -> P z.+1
P: Int -> Type t0: P zero f: forallz0 : Int, P z0 <-> P z0.+1 z: Int
P z -> P z.+1
exact (fst (f z)).
P: Int -> Type t0: P zero f: forallz : Int, P z <-> P z.+1
forallz : Int, P z -> P z.-1
P: Int -> Type t0: P zero f: forallz0 : Int, P z0 <-> P z0.+1 z: Int
P z.+1 -> P z.+1.-1
P: Int -> Type t0: P zero f: forallz0 : Int, P z0 <-> P z0.+1 z: Int
P z -> P z.+1.-1
exact (transport P (int_pred_succ z)^).Defined.(** ** Printing and parsing *)(** We pass through [SInt] for printing and parsing. *)Definitionint_to_number_int : Int -> Numeral.int := sint_to_number_int o int_to_sint.Definitionint_of_number_int : Numeral.int -> Int := sint_to_int o sint_of_number_int.Number NotationInt int_of_number_int int_to_number_int : int_scope.(** ** Integer arithmetic *)(** *** Negation *)Definitionint_neg (z : Int) : Int
:= int_rec_equiv zero int_pred z.Notation"- z" := (int_neg z) : int_scope.(** Negation is involutive. *)
z: Int
- - z = z
z: Int
- - z = z
forallz : Int, - - z = z
by srapply (int_homotopic int_succ).Defined.(** Negation is an equivalence. *)
IsEquiv int_neg
IsEquiv int_neg
int_neg o int_neg == idmap
int_neg o int_neg == idmap
1,2: napply int_neg_neg.Defined.(** Negation is injective. *)Definitionisinj_int_neg (xy : Int) : -x = -y -> x = y
:= equiv_inj int_neg.(** The negation of a successor is the predecessor of the negation. *)Definitionint_neg_succ (z : Int) : -(z.+1) = (-z).-1
:= idpath.(** The negation of a predecessor is the successor of the negation. *)Definitionint_neg_pred (z : Int) : -(z.-1) = (-z).+1
:= idpath.(** *** Addition *)(** We define addition by recursion on the first argument. *)Definitionint_add (xy : Int) : Int
:= int_iter int_succ x y.Infix"+" := int_add : int_scope.Infix"-" := (funxy => x + -y) : int_scope.(** Integer addition with zero on the left is the identity by definition. *)Definitionint_add_0_l (z : Int) : 0 + z = z
:= idpath.(** Adding a successor on the left is the successor of the sum. *)Definitionint_add_succ_l (xy : Int) : x.+1 + y = (x + y).+1
:= idpath.(** Adding a predecessor on the left is the predecessor of the sum. *)Definitionint_add_pred_l (xy : Int) : x.-1 + y = (x + y).-1
:= idpath.(** Integer addition with 1 on the left is the successor. *)Definitionint_add_1_l (z : Int) : 1 + z = z.+1
:= idpath.(** Integer addition with zero on the right is the identity. *)
z: Int
z + 0 = z
z: Int
z + 0 = z
forallz : Int, z + 0 = z
by srapply (int_homotopic int_succ).Defined.(** Adding a successor on the right is the successor of the sum. *)
x, y: Int
x + y.+1 = (x + y).+1
x, y: Int
x + y.+1 = (x + y).+1
y: Int
forallx : Int, x + y.+1 = (x + y).+1
by srapply (int_homotopic int_succ).Defined.(** Integer addition is commutative. *)
x, y: Int
x + y = y + x
x, y: Int
x + y = y + x
y: Int
forallx : Int, x + y = y + x
y: Int
0 + y = y + 0
y: Int
(funx : Int => x.+1 + y) == (funx : Int => (x + y).+1)
y: Int
(funx : Int => y + x.+1) == (funx : Int => (y + x).+1)
y: Int
0 + y = y + 0
byrewrite int_add_0_r.
y: Int
(funx : Int => x.+1 + y) == (funx : Int => (x + y).+1)
reflexivity.
y: Int
(funx : Int => y + x.+1) == (funx : Int => (y + x).+1)
y, z: Int
y + z.+1 = (y + z).+1
byrewrite int_add_succ_r.Defined.(** Adding a predecessor on the right is the predecessor of the sum. *)Definitionint_add_pred_r (xy : Int) : x + y.-1 = (x + y).-1
:= int_add_comm x y.-1 @ ap int_pred (int_add_comm y x).(** Integer addition with 1 on the right is the successor. *)
z: Int
z + 1 = z.+1
z: Int
z + 1 = z.+1
forallz : Int, z + 1 = z.+1
by srapply (int_homotopic int_succ).Defined.(** Integer addition is associative. *)
x, y, z: Int
x + (y + z) = x + y + z
x, y, z: Int
x + (y + z) = x + y + z
y, z: Int
forallx : Int, x + (y + z) = x + y + z
by srapply (int_homotopic int_succ).Defined.(** Negation is a left inverse with respect to integer addition. *)
z: Int
- z + z = 0
z: Int
- z + z = 0
forallz : Int, - z + z = 0
- 0 + 0 = 0
(funx : Int => - x.+1 + x.+1) == (funx : Int => - x + x)
(fun_ : Int => 0) == (fun_ : Int => 0)
(funx : Int => - x.+1 + x.+1) == (funx : Int => - x + x)
s: Int
(- s + s.+1).-1 = - s + s
s: Int
(- s + s).+1.-1 = - s + s
apply int_pred_succ.Defined.(** Negation is a right inverse with respect to integer addition. *)Definitionint_add_neg_r (z : Int) : z - z = 0
:= int_add_comm _ _ @ int_add_neg_l _.(** Negation distributes over addition. *)
x, y: Int
- (x + y) = - x - y
x, y: Int
- (x + y) = - x - y
y: Int
forallx : Int, - (x + y) = - x - y
by srapply (int_homotopic int_pred).Defined.(** Addition is an equivalence with first argument fixed. *)
x: Int
IsEquiv (int_add x)
x: Int
IsEquiv (int_add x)
x: Int
int_add x o int_add (- x) == idmap
x: Int
int_add (- x) o int_add x == idmap
x, y: Int
x + (- x + y) = y
x, y: Int
- x + (x + y) = y
x, y: Int
x + - x + y = y
x, y: Int
- x + x + y = y
x, y: Int
x + - x + y = y
byrewrite int_add_neg_r.
x, y: Int
- x + x + y = y
byrewrite int_add_neg_l.Defined.(** Addition is an equivalence with second argument fixed. This also follows from the previous result and [int_add_comm], but this proof computes better. *)
y: Int
IsEquiv (funx : Int => x + y)
y: Int
IsEquiv (funx : Int => x + y)
y: Int
(funx : Int => x + y) o (funx : Int => x - y) == idmap
y: Int
(funx : Int => x - y) o (funx : Int => x + y) == idmap
y, x: Int
x + - y + y = x
y, x: Int
x + y + - y = x
y, x: Int
x + (- y + y) = x
y, x: Int
x + (y + - y) = x
y, x: Int
x + (- y + y) = x
y, x: Int
x + 0 = x
apply int_add_0_r.
y, x: Int
x + (y + - y) = x
y, x: Int
x + 0 = x
apply int_add_0_r.Defined.(** *** Multiplication *)(** We define multiplication by recursion on the first argument. This depends on the proof that addition is an equivalence. *)Definitionint_mul (xy : Int) : Int
:= int_iter (funz => z + y) x 0.Infix"*" := int_mul : int_scope.(** Integer multiplication with zero on the left is zero by definition. *)Definitionint_mul_0_l (z : Int) : 0 * z = 0
:= idpath.(** Multiplication with a successor on the left adds the other argument. *)Definitionint_mul_succ_l (xy : Int) : x.+1 * y = x * y + y
:= idpath.(** Multiplication with a predecessor on the left subtracts the other argument. *)Definitionint_mul_pred_l (xy : Int) : x.-1 * y = x * y - y
:= idpath.(** Integer multiplication with one on the left is the identity. *)Definitionint_mul_1_l (z : Int) : 1 * z = z
:= idpath.(** Integer multiplication with [-1] on the left is negation. *)Definitionint_mul_neg1_l (z : Int) : -1 * z = -z
:= idpath.(** Multiplying with a negation on the left is the same as negating the product. *)
x, y: Int
- x * y = - (x * y)
x, y: Int
- x * y = - (x * y)
y: Int
forallx : Int, - x * y = - (x * y)
y: Int
- 0 * y = - (0 * y)
y: Int
(funx : Int => - x.+1 * y) == (funx : Int => - x * y + - y)
y: Int
(funx : Int => - (x.+1 * y)) == (funx : Int => - (x * y) + - y)
y: Int
(funx : Int => - (x.+1 * y)) == (funx : Int => - (x * y) + - y)
y, x: Int
- (x * y + y) = - (x * y) + - y
apply int_neg_add.Defined.(** Multiplication distributes over addition on the left. *)
x, y, z: Int
x * (y + z) = x * y + x * z
x, y, z: Int
x * (y + z) = x * y + x * z
y, z: Int
forallx : Int, x * (y + z) = x * y + x * z
y, z: Int
0 * (y + z) = 0 * y + 0 * z
y, z: Int
(funx : Int => x.+1 * (y + z)) == (funx : Int => x * (y + z) + (y + z))
y, z: Int
(funx : Int => x.+1 * y + x.+1 * z) ==
(funx : Int => x * y + x * z + (y + z))
y, z: Int
(funx : Int => x.+1 * y + x.+1 * z) ==
(funx : Int => x * y + x * z + (y + z))
y, z, x: Int
x * y + y + (x * z + z) = x * y + x * z + (y + z)
y, z, x: Int
x * y + (y + (x * z + z)) = x * y + x * z + (y + z)
y, z, x: Int
x * y + (x * z + z + y) = x * y + x * z + (y + z)
y, z, x: Int
x * y + (x * z + z + y) = x * y + x * z + (z + y)
byrewrite <- 2 int_add_assoc.Defined.(** Integer multiplication with zero on the right is zero. *)
z: Int
z * 0 = 0
z: Int
z * 0 = 0
forallz : Int, z * 0 = 0
0 * 0 = 0
(funx : Int => x.+1 * 0) == (funx : Int => x * 0)
(fun_ : Int => 0) == (fun_ : Int => 0)
(funx : Int => x.+1 * 0) == (funx : Int => x * 0)
z: Int
z * 0 + 0 = z * 0
apply int_add_0_r.Defined.(** Multiplying with a successor on the right adds the other argument. *)
x, y: Int
x * y.+1 = x + x * y
x, y: Int
x * y.+1 = x + x * y
y: Int
forallx : Int, x * y.+1 = x + x * y
y: Int
0 * y.+1 = 0 + 0 * y
y: Int
(funx : Int => x.+1 * y.+1) == (funx : Int => x * y.+1 + y.+1)
y: Int
(funx : Int => x.+1 + x.+1 * y) == (funx : Int => x + x * y + y.+1)
y: Int
(funx : Int => x.+1 + x.+1 * y) == (funx : Int => x + x * y + y.+1)
y, z: Int
(z + (z * y + y)).+1 = z + z * y + y.+1
y, z: Int
(z + (z * y + y)).+1 = (z + z * y + y).+1
byrewrite int_add_assoc.Defined.(** Multiplication is commutative. *)
x, y: Int
x * y = y * x
x, y: Int
x * y = y * x
y: Int
forallx : Int, x * y = y * x
y: Int
0 * y = y * 0
y: Int
(funx : Int => x.+1 * y) == (funx : Int => x * y + y)
y: Int
(funx : Int => y * x.+1) == (funx : Int => y * x + y)
y: Int
0 * y = y * 0
symmetry; apply int_mul_0_r.
y: Int
(funx : Int => x.+1 * y) == (funx : Int => x * y + y)
reflexivity.
y: Int
(funx : Int => y * x.+1) == (funx : Int => y * x + y)
y, z: Int
y * z.+1 = y * z + y
y, z: Int
y * z.+1 = y + y * z
apply int_mul_succ_r.Defined.(** Multiplying with a predecessor on the right subtracts the other argument. *)Definitionint_mul_pred_r (xy : Int) : x * y.-1 = x * y - x
:= int_mul_comm x y.-1 @ ap _ (int_mul_comm y x).(** Integer multiplication with one on the right is the identity. *)Definitionint_mul_1_r (z : Int) : z * 1 = z
:= int_mul_comm _ _.(** Multiplying with a negation on the right is the same as negating the product. *)Definitionint_mul_neg_r (xy : Int) : x * -y = -(x * y)
:= int_mul_comm _ _ @ int_mul_neg_l _ _ @ ap _ (int_mul_comm _ _).(** Multiplication distributes over addition on the right. *)
x, y, z: Int
(x + y) * z = x * z + y * z
x, y, z: Int
(x + y) * z = x * z + y * z
byrewrite int_mul_comm, int_dist_l, !(int_mul_comm z).Defined.(** Multiplication is associative. *)
x, y, z: Int
x * (y * z) = x * y * z
x, y, z: Int
x * (y * z) = x * y * z
y, z: Int
forallx : Int, x * (y * z) = x * y * z
y, z: Int
0 * (y * z) = 0 * y * z
y, z: Int
(funx : Int => x.+1 * (y * z)) == (funx : Int => x * (y * z) + y * z)
y, z: Int
(funx : Int => x.+1 * y * z) == (funx : Int => x * y * z + y * z)
y, z: Int
(funx : Int => x.+1 * y * z) == (funx : Int => x * y * z + y * z)
y, z, x: Int
(x * y + y) * z = x * y * z + y * z
byrewrite int_dist_r.Defined.(** ** Results about iteration of equivalences *)
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f (- z) a = int_iter f^-1 z a
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f (- z) a = int_iter f^-1 z a
A: Type f: A -> A H: IsEquiv f a: A
forallz : Int, int_iter f (- z) a = int_iter f^-1 z a
by srapply (int_homotopic f^-1).Defined.Definitionint_iter_succ_l {A} (f : A -> A) `{IsEquiv _ _ f} (z : Int) (a : A)
: int_iter f z.+1 a = f (int_iter f z a)
:= idpath.
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f z.+1 a = int_iter f z (f a)
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f z.+1 a = int_iter f z (f a)
A: Type f: A -> A H: IsEquiv f a: A
forallz : Int, int_iter f z.+1 a = int_iter f z (f a)
by srapply (int_homotopic f).Defined.Definitionint_iter_pred_l {A} (f : A -> A) `{IsEquiv _ _ f} (z : Int) (a : A)
: int_iter f z.-1 a = f^-1 (int_iter f z a)
:= idpath.
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f z.-1 a = int_iter f z (f^-1 a)
A: Type f: A -> A H: IsEquiv f z: Int a: A
int_iter f z.-1 a = int_iter f z (f^-1 a)
A: Type f: A -> A H: IsEquiv f a: A
forallz : Int, int_iter f z.-1 a = int_iter f z (f^-1 a)
A: Type f: A -> A H: IsEquiv f a: A
int_iter f (-1) a = int_iter f 0 (f^-1 a)
A: Type f: A -> A H: IsEquiv f a: A
(funx : Int => int_iter f x.+1.-1 a) ==
(funx : Int => f (int_iter f x.-1 a))
A: Type f: A -> A H: IsEquiv f a: A
(funx : Int => int_iter f x.+1 (f^-1 a)) ==
(funx : Int => f (int_iter f x (f^-1 a)))
A: Type f: A -> A H: IsEquiv f a: A
(funx : Int => int_iter f x.+1.-1 a) ==
(funx : Int => f (int_iter f x.-1 a))
A: Type f: A -> A H: IsEquiv f a: A z: Int
f^-1 (f (int_iter f z a)) = f (f^-1 (int_iter f z a))
exact (eissect f (int_iter f z a) @ (eisretr f (int_iter f z a))^).Defined.
A: Type f: A -> A H: IsEquiv f x, y: Int
int_iter f (x + y) == int_iter f x o int_iter f y
A: Type f: A -> A H: IsEquiv f x, y: Int
int_iter f (x + y) == int_iter f x o int_iter f y
A: Type f: A -> A H: IsEquiv f y: Int a: A
forallx : Int, int_iter f (x + y) a = int_iter f x (int_iter f y a)
by srapply (int_homotopic f).Defined.(** If [g : A -> A'] commutes with automorphisms of [A] and [A'], then it commutes with iteration. *)
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g z: Int a: A
g (int_iter f z a) = int_iter f' z (g a)
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g z: Int a: A
g (int_iter f z a) = int_iter f' z (g a)
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g a: A
forallz : Int, g (int_iter f z a) = int_iter f' z (g a)
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g a: A
g (int_iter f 0 a) = int_iter f' 0 (g a)
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g a: A
(funx : Int => g (int_iter f x.+1 a)) ==
(funx : Int => f' (g (int_iter f x a)))
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g a: A
(funx : Int => int_iter f' x.+1 (g a)) ==
(funx : Int => f' (int_iter f' x (g a)))
A, A': Type f: A -> A IsEquiv0: IsEquiv f f': A' -> A' IsEquiv1: IsEquiv f' g: A -> A' p: g o f == f' o g a: A
(funx : Int => g (int_iter f x.+1 a)) ==
(funx : Int => f' (g (int_iter f x a)))
intro x; apply p.Defined.(** In particular, homotopic maps have homotopic iterations. *)Definitionint_iter_homotopic (z : Int) {A} (ff' : A -> A) `{!IsEquiv f} `{!IsEquiv f'}
(h : f == f')
: int_iter f z == int_iter f' z
:= int_iter_commute_map f f' idmap h z.(** [int_iter f n x] doesn't depend on the proof that [f] is an equivalence. *)Definitionint_iter_agree (z : Int) {A} (f : A -> A) {iefief' : IsEquiv f}
: forallx, @int_iter A f ief z x = @int_iter A f ief' z x
:= int_iter_homotopic z f f (fun_ => idpath).(** An important invariance property of iteration. The most obvious proof attempts fail, for the reasons described in the comment for [int_ind_sint]. *)
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0)
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0)
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
P a0
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0) -> P (f (int_rec_equiv a0 f z))
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0) -> P (f^-1 (int_rec_equiv a0 f z))
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
P a0
exact Pa0.
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0) -> P (f (int_rec_equiv a0 f z))
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0 z: Int IH: P (int_iter f z a0)
P (f (int_rec_equiv a0 f z))
apply Psucc, IH.
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0
forallz : Int, P (int_iter f z a0) -> P (f^-1 (int_rec_equiv a0 f z))
A: Type f: A -> A IsEquiv0: IsEquiv f P: A -> Type Psucc: foralla : A, P a -> P (f a) Ppred: foralla : A, P a -> P (f^-1 a) a0: A Pa0: P a0 z: Int IH: P (int_iter f z a0)
P (f^-1 (int_rec_equiv a0 f z))
apply Ppred, IH.Defined.(** ** Exponentiation of loops *)Definitionloopexp {A : Type} {a : A} (p : a = a) (z : Int) : (a = a)
:= int_iter (equiv_concat_r p a) z idpath.Definitionloopexp_succ_r {A : Type} {a : A} (p : a = a) (z : Int)
: loopexp p z.+1 = loopexp p z @ p
:= idpath.Definitionloopexp_pred_r {A : Type} {a : A} (p : a = a) (z : Int)
: loopexp p z.-1 = loopexp p z @ p^
:= idpath.
A: Type a: A p: a = a z: Int
loopexp p z.+1 = p @ loopexp p z
A: Type a: A p: a = a z: Int
loopexp p z.+1 = p @ loopexp p z
A: Type a: A p: a = a
forallz : Int, loopexp p z @ p = p @ loopexp p z
A: Type a: A p: a = a
loopexp p 0 @ p = p @ loopexp p 0
A: Type a: A p: a = a
(funx : Int => loopexp p x.+1 @ p) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ p))
A: Type a: A p: a = a
(funx : Int => p @ loopexp p x.+1) ==
(funx : Int => equiv_concat_r p a (p @ loopexp p x))
A: Type a: A p: a = a
loopexp p 0 @ p = p @ loopexp p 0
napply concat_1p_p1.
A: Type a: A p: a = a
(funx : Int => loopexp p x.+1 @ p) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ p))
reflexivity.
A: Type a: A p: a = a
(funx : Int => p @ loopexp p x.+1) ==
(funx : Int => equiv_concat_r p a (p @ loopexp p x))
A: Type a: A p: a = a z: Int
p @ (loopexp p z @ p) = (p @ loopexp p z) @ p
apply concat_p_pp.Defined.
A: Type a: A p: a = a z: Int
loopexp p z.-1 = p^ @ loopexp p z
A: Type a: A p: a = a z: Int
loopexp p z.-1 = p^ @ loopexp p z
A: Type a: A p: a = a
forallz : Int, loopexp p z @ p^ = p^ @ loopexp p z
A: Type a: A p: a = a
loopexp p 0 @ p^ = p^ @ loopexp p 0
A: Type a: A p: a = a
(funx : Int => loopexp p x.+1 @ p^) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ p^))
A: Type a: A p: a = a
(funx : Int => p^ @ loopexp p x.+1) ==
(funx : Int => equiv_concat_r p a (p^ @ loopexp p x))
A: Type a: A p: a = a
loopexp p 0 @ p^ = p^ @ loopexp p 0
napply concat_1p_p1.
A: Type a: A p: a = a
(funx : Int => loopexp p x.+1 @ p^) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ p^))
A: Type a: A p: a = a z: Int
(loopexp p z @ p) @ p^ = (loopexp p z @ p^) @ p
exact (concat_pp_V _ _ @ (concat_pV_p _ _)^).
A: Type a: A p: a = a
(funx : Int => p^ @ loopexp p x.+1) ==
(funx : Int => equiv_concat_r p a (p^ @ loopexp p x))
A: Type a: A p: a = a z: Int
p^ @ (loopexp p z @ p) = (p^ @ loopexp p z) @ p
apply concat_p_pp.Defined.
A, B: Type f: A -> B a: A p: a = a z: Int
ap f (loopexp p z) = loopexp (ap f p) z
A, B: Type f: A -> B a: A p: a = a z: Int
ap f (loopexp p z) = loopexp (ap f p) z
A, B: Type f: A -> B a: A p: a = a z: Int
(funx : a = a => ap f (equiv_concat_r p a x)) ==
(funx : a = a => equiv_concat_r (ap f p) (f a) (ap f x))
intro q; apply ap_pp.Defined.
A: Type a: A p: a = a x, y: Int
loopexp p (x + y) = loopexp p x @ loopexp p y
A: Type a: A p: a = a x, y: Int
loopexp p (x + y) = loopexp p x @ loopexp p y
A: Type a: A p: a = a y: Int
forallx : Int, loopexp p (x + y) = loopexp p x @ loopexp p y
A: Type a: A p: a = a y: Int
loopexp p (0 + y) = loopexp p 0 @ loopexp p y
A: Type a: A p: a = a y: Int
(funx : Int => loopexp p (x.+1 + y)) ==
(funx : Int => equiv_concat_r p a (loopexp p (x + y)))
A: Type a: A p: a = a y: Int
(funx : Int => loopexp p x.+1 @ loopexp p y) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ loopexp p y))
A: Type a: A p: a = a y: Int
loopexp p (0 + y) = loopexp p 0 @ loopexp p y
symmetry; apply concat_1p.
A: Type a: A p: a = a y: Int
(funx : Int => loopexp p (x.+1 + y)) ==
(funx : Int => equiv_concat_r p a (loopexp p (x + y)))
reflexivity.
A: Type a: A p: a = a y: Int
(funx : Int => loopexp p x.+1 @ loopexp p y) ==
(funx : Int => equiv_concat_r p a (loopexp p x @ loopexp p y))
A: Type a: A p: a = a y, z: Int
(loopexp p z @ p) @ loopexp p y = (loopexp p z @ loopexp p y) @ p
A: Type a: A p: a = a y, z: Int
loopexp p z @ (p @ loopexp p y) = loopexp p z @ (loopexp p y @ p)
byrewrite <- loopexp_succ_l.Defined.(** Under univalence, exponentiation of loops corresponds to iteration of auto-equivalences. *)
A: Type p: A = A z: Int a: A
equiv_path A A (loopexp p z) a = int_iter (equiv_path A A p) z a
A: Type p: A = A z: Int a: A
equiv_path A A (loopexp p z) a = int_iter (equiv_path A A p) z a
A: Type p: A = A z: Int a: A
(funx : A = A => equiv_path A A (equiv_concat_r p A x) a) ==
(funx : A = A => equiv_path A A p (equiv_path A A x a))
A: Type p: A = A z: Int a: A q: A = A
transport idmap (q @ p) a = transport idmap p (transport idmap q a)
napply transport_pp.Defined.
H: Univalence A: Type f: A <~> A z: Int a: A
transport idmap (loopexp (path_universe f) z) a = int_iter f z a
H: Univalence A: Type f: A <~> A z: Int a: A
transport idmap (loopexp (path_universe f) z) a = int_iter f z a
H: Univalence A: Type z: Int a: A p: A = A
transport idmap (loopexp (path_universe (equiv_path A A p)) z) a =
int_iter (equiv_path A A p) z a
H: Univalence A: Type z: Int a: A p: A = A
transport idmap (loopexp (path_universe (equiv_path A A p)) z) a =
equiv_path A A (loopexp p z) a
H: Univalence A: Type z: Int a: A p: A = A
path_universe (equiv_path A A p) = p
apply eissect.Defined.(** ** Converting between integers and naturals *)(** We can convert a [nat] to an [Int] by mapping [0] to [zero] and [S n] to [int_succ n]. Various operations on [nat] are preserved by this function. We will make this into a coercion later; we delay doing so to ensure that the lemmas about [int_of_nat] are interpreted as we want them to be. *)Definitionint_of_nat (n : nat) : Int
:= nat_iter n int_succ zero.(** [int_of_nat] preserves zero. *)Definitionint_of_nat_zero : int_of_nat 0 = 0
:= idpath.(** [int_of_nat] preserves successors. *)Definitionint_of_nat_succ (n : nat)
: int_of_nat (n.+1) = (int_of_nat n).+1
:= idpath.(** [int_of_nat] preserves predecessors of positive naturals. *)