diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f4b6a55a8..d5f30317d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,7 +6,7 @@ Please include a quick description of the changes here. Before submitting a merge request, please check the items below: -- [ ] The imports are sorted (use `find -type f -name \*.agda -or -name \*.lagda.md | xargs support/sort-imports.hs`) +- [ ] The imports are sorted with `support/sort-imports.hs` - [ ] All code blocks have "agda" as their language. This is so that tools like Tokei can report accurate line counts for proofs vs. text. diff --git a/1lab.agda-lib b/1lab.agda-lib index cf3ed3e66..655e99e19 100644 --- a/1lab.agda-lib +++ b/1lab.agda-lib @@ -1,4 +1,4 @@ -name: cubical-1lab +name: 1lab include: src wip diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b8e32aa48..c17f91c8a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ Thanks for taking the time to contribute! This file holds the conventions we use around the codebase, but they're guidelines, and not strict rules: If you're unsure of something, hop on [the Discord](https://discord.gg/Zp2e8hYsuX) and ask there, or open [a -discussion thread](https://github.com/plt-amy/cubical-1lab/discussions) +discussion thread](https://github.com/plt-amy/1lab/discussions) if that's more your style. ### General guidelines @@ -14,7 +14,8 @@ if that's more your style. Use British spelling everywhere that it differs from American: Homotopy fib**re**, fib**red** category, colo**u**red operad, etc --- both in prose and in Agda. Keep prose paragraphs limited to 72 characters of -length. Prefer link anchors (Pandoc "reference links") to inline links. +length. Prefer wikilinks or link anchors (Pandoc "reference links") to +inline links. ### Agda code style diff --git a/README.md b/README.md index 0120c8184..5048f86ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Discord](https://img.shields.io/discord/914172963157323776?label=Discord&logo=discord)](https://discord.gg/Zp2e8hYsuX) -[![Build 1Lab](https://github.com/plt-amy/cubical-1lab/actions/workflows/build.yml/badge.svg)](https://github.com/plt-amy/cubical-1lab/actions/workflows/build.yml) +[![Build 1Lab](https://github.com/plt-amy/1lab/actions/workflows/build.yml/badge.svg)](https://github.com/plt-amy/1lab/actions/workflows/build.yml) # [1Lab](https://1lab.dev) diff --git a/default.nix b/default.nix index 0aaa13c68..aa1361a38 100644 --- a/default.nix +++ b/default.nix @@ -2,9 +2,10 @@ inNixShell ? false # Do we want the full Agda package for interactive use? Set to false in CI , interactive ? true +, system ? builtins.currentSystem }: let - pkgs = import ./support/nix/nixpkgs.nix; + pkgs = import ./support/nix/nixpkgs.nix { inherit system; }; inherit (pkgs) lib; our-ghc = pkgs.labHaskellPackages.ghcWithPackages (ps: with ps; [ diff --git a/package-lock.json b/package-lock.json index 007257bfc..f0a58b9fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "cubical-1lab", + "name": "1lab", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "cubical-1lab", + "name": "1lab", "version": "1.0.0", "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 55197b704..fa35d7f73 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "cubical-1lab", + "name": "1lab", "version": "1.0.0", "description": " A formalised, cross-linked reference resource for mathematics done in Homotopy Type Theory ", "main": "index.js", @@ -8,14 +8,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/plt-amy/cubical-1lab.git" + "url": "git+https://github.com/plt-amy/1lab.git" }, "author": "Amélia Liao et. al.", "license": "AGPL-3.0", "bugs": { - "url": "https://github.com/plt-amy/cubical-1lab/issues" + "url": "https://github.com/plt-amy/1lab/issues" }, - "homepage": "https://github.com/plt-amy/cubical-1lab#readme", + "homepage": "https://github.com/plt-amy/1lab#readme", "devDependencies": { "@types/d3": "^7.1.0", "d3": "^7.4.4", diff --git a/src/1Lab/Equiv/Biinv.lagda.md b/src/1Lab/Equiv/Biinv.lagda.md index 4142c7247..a2380799e 100644 --- a/src/1Lab/Equiv/Biinv.lagda.md +++ b/src/1Lab/Equiv/Biinv.lagda.md @@ -176,11 +176,11 @@ suffices to show that `is-biinv`{.Agda} is contractible when it is inhabited: [a proposition]: agda://1Lab.HLevel#is-prop -[contractible if inhabited]: agda://1Lab.HLevel#contractible-if-inhabited +[contractible if inhabited]: agda://1Lab.HLevel#is-contr-if-inhabited→is-prop ```agda is-biinv-is-prop : {f : A → B} → is-prop (is-biinv f) -is-biinv-is-prop {f = f} = contractible-if-inhabited contract where +is-biinv-is-prop {f = f} = is-contr-if-inhabited→is-prop contract where contract : is-biinv f → is-contr (is-biinv f) contract ibiinv = ×-is-hlevel 0 (is-iso→is-contr-linv iiso) diff --git a/src/1Lab/Equiv/HalfAdjoint.lagda.md b/src/1Lab/Equiv/HalfAdjoint.lagda.md index bce7353e4..ca00c9211 100644 --- a/src/1Lab/Equiv/HalfAdjoint.lagda.md +++ b/src/1Lab/Equiv/HalfAdjoint.lagda.md @@ -176,7 +176,7 @@ another $(x, p)$ using a very boring calculation: path : ap f (ap g (sym p) ∙ η x) ∙ p ≡ ε y path = - ap f (ap g (sym p) ∙ η x) ∙ p ≡⟨ ap₂ _∙_ (ap-comp-path f (ap g (sym p)) (η x)) refl ∙ sym (∙-assoc _ _ _) ⟩ + ap f (ap g (sym p) ∙ η x) ∙ p ≡⟨ ap₂ _∙_ (ap-∙ f (ap g (sym p)) (η x)) refl ∙ sym (∙-assoc _ _ _) ⟩ ap (λ x → f (g x)) (sym p) ∙ ⌜ ap f (η x) ⌝ ∙ p ≡⟨ ap! (zig _) ⟩ -- by the triangle identity ap (f ∘ g) (sym p) ∙ ⌜ ε (f x) ∙ p ⌝ ≡⟨ ap! (homotopy-natural ε p) ⟩ -- by naturality of ε ``` @@ -189,7 +189,7 @@ $\varepsilon$ lets us "push it past $p$" to get something we can cancel: ```agda ap (f ∘ g) (sym p) ∙ ap (f ∘ g) p ∙ ε y ≡⟨ ∙-assoc _ _ _ ⟩ - ⌜ ap (f ∘ g) (sym p) ∙ ap (f ∘ g) p ⌝ ∙ ε y ≡˘⟨ ap¡ (ap-comp-path (f ∘ g) (sym p) p) ⟩ + ⌜ ap (f ∘ g) (sym p) ∙ ap (f ∘ g) p ⌝ ∙ ε y ≡˘⟨ ap¡ (ap-∙ (f ∘ g) (sym p) p) ⟩ ap (f ∘ g) ⌜ sym p ∙ p ⌝ ∙ ε y ≡⟨ ap! (∙-inv-r _) ⟩ ap (f ∘ g) refl ∙ ε y ≡⟨⟩ refl ∙ ε y ≡⟨ ∙-id-l (ε y) ⟩ diff --git a/src/1Lab/HIT/Truncation.lagda.md b/src/1Lab/HIT/Truncation.lagda.md index 9986aa848..c52af2a4a 100644 --- a/src/1Lab/HIT/Truncation.lagda.md +++ b/src/1Lab/HIT/Truncation.lagda.md @@ -48,7 +48,7 @@ is-prop-∥-∥ = squash ```agda instance H-Level-truncation : ∀ {n} {ℓ} {A : Type ℓ} → H-Level ∥ A ∥ (suc n) - H-Level-truncation = hlevel-instance (is-prop→is-hlevel-suc squash) + H-Level-truncation = prop-instance squash ``` --> diff --git a/src/1Lab/HLevel.lagda.md b/src/1Lab/HLevel.lagda.md index b5c4a15b2..0c6672ace 100644 --- a/src/1Lab/HLevel.lagda.md +++ b/src/1Lab/HLevel.lagda.md @@ -9,7 +9,7 @@ open import 1Lab.Type module 1Lab.HLevel where ``` -# h-Levels +# h-Levels {defines="h-level n-type truncated"} The "homotopy level" (h-level for short) of a type is a measure of how [truncated] it is, where the numbering is offset by 2. Specifically, a @@ -36,8 +36,10 @@ _homotopy $(n-2)$-types_. For instance: "The sets are the homotopy 0-types". The use of the $-2$ offset is so the naming here matches that of the HoTT book. +:::{.definition #contractible} The h-levels are defined by induction, where the base case are the _contractible types_. +::: [truncated]: https://ncatlab.org/nlab/show/truncated+object @@ -77,7 +79,7 @@ type. interval-contractible .paths (seg i) j = seg (i ∧ j) ``` -:::{.definition #proposition} +:::{.definition #proposition alias="property"} A type is (n+1)-truncated if its path types are all n-truncated. However, if we directly take this as the definition, the types we end up with are very inconvenient! That's why we introduce this immediate step: @@ -114,7 +116,9 @@ is-set : ∀ {ℓ} → Type ℓ → Type ℓ is-set A = is-hlevel A 2 ``` +:::{.definition #groupoid} Similarly, the types of h-level 3 are called **groupoids**. +::: ```agda is-groupoid : ∀ {ℓ} → Type ℓ → Type ℓ @@ -182,8 +186,12 @@ which is that the propositions are precisely the types which are contractible when they are inhabited: ```agda -contractible-if-inhabited : ∀ {ℓ} {A : Type ℓ} → (A → is-contr A) → is-prop A -contractible-if-inhabited cont x y = is-contr→is-prop (cont x) x y +is-contr-if-inhabited→is-prop : ∀ {ℓ} {A : Type ℓ} → (A → is-contr A) → is-prop A +is-contr-if-inhabited→is-prop cont x y = is-contr→is-prop (cont x) x y + +is-prop→is-contr-if-inhabited : ∀ {ℓ} {A : Type ℓ} → is-prop A → A → is-contr A +is-prop→is-contr-if-inhabited prop x .centre = x +is-prop→is-contr-if-inhabited prop x .paths y = prop x y ``` The proof that any contractible type is a proposition is not too @@ -372,6 +380,13 @@ is-hlevel-is-prop (suc (suc n)) x y i a b = is-hlevel-is-prop (suc n) (x a b) (y a b) i ``` + + # Dependent h-Levels In cubical type theory, it's natural to consider a notion of _dependent_ diff --git a/src/1Lab/HLevel/Retracts.lagda.md b/src/1Lab/HLevel/Retracts.lagda.md index 002ad46c3..5a2770464 100644 --- a/src/1Lab/HLevel/Retracts.lagda.md +++ b/src/1Lab/HLevel/Retracts.lagda.md @@ -352,9 +352,10 @@ instance H-Level-sigma {n = n} .H-Level.has-hlevel = Σ-is-hlevel n (hlevel n) λ _ → hlevel n - H-Level-path′ - : ∀ {n} ⦃ s : H-Level S (suc n) ⦄ {x y} → H-Level (Path S x y) n - H-Level-path′ {n = n} .H-Level.has-hlevel = Path-is-hlevel' n (hlevel (suc n)) _ _ + H-Level-PathP + : ∀ {n} {S : I → Type ℓ} ⦃ s : H-Level (S i1) (suc n) ⦄ {x y} + → H-Level (PathP S x y) n + H-Level-PathP {n = n} .H-Level.has-hlevel = PathP-is-hlevel' n (hlevel (suc n)) _ _ H-Level-Lift : ∀ {n} ⦃ s : H-Level T n ⦄ → H-Level (Lift ℓ T) n diff --git a/src/1Lab/Path.lagda.md b/src/1Lab/Path.lagda.md index 0db153116..54c1caf50 100644 --- a/src/1Lab/Path.lagda.md +++ b/src/1Lab/Path.lagda.md @@ -268,6 +268,21 @@ Square : ∀ {ℓ} {A : Type ℓ} {a00 a01 a10 a11 : A} Square p q s r = PathP (λ i → p i ≡ r i) q s ``` + + The arguments to `Square`{.Agda} are as in the following diagram, listed in the order “PQSR”. This order is a bit unusual (it's one off from being alphabetical, for instance) but it does have a significant @@ -1028,6 +1043,8 @@ be reflexivity. For definiteness, we chose the left face: _∙_ : ∀ {ℓ} {A : Type ℓ} {x y z : A} → x ≡ y → y ≡ z → x ≡ z p ∙ q = refl ·· p ·· q + +infixr 30 _∙_ ``` The ordinary, “single composite” of $p$ and $q$ is the dashed face in @@ -1061,17 +1078,29 @@ setting the _right_ face to `refl`{.Agda}. ``` We can use the filler and heterogeneous composition to define composition of `PathP`{.Agda}s -in a given type family: +and `Square`{.Agda}s: ```agda _∙P_ : ∀ {ℓ ℓ′} {A : Type ℓ} {B : A → Type ℓ′} {x y z : A} {x′ : B x} {y′ : B y} {z′ : B z} {p : x ≡ y} {q : y ≡ z} - → PathP (λ i → B (p i)) x′ y′ → PathP (λ i → B (q i)) y′ z′ + → PathP (λ i → B (p i)) x′ y′ + → PathP (λ i → B (q i)) y′ z′ → PathP (λ i → B ((p ∙ q) i)) x′ z′ _∙P_ {B = B} {x′ = x′} {p = p} {q = q} p′ q′ i = comp (λ j → B (∙-filler p q j i)) (∂ i) λ where j (i = i0) → x′ j (i = i1) → q′ j j (j = i0) → p′ i + +_∙₂_ : ∀ {ℓ} {A : Type ℓ} {a00 a01 a02 a10 a11 a12 : A} + {p : a00 ≡ a01} {p′ : a01 ≡ a02} + {q : a00 ≡ a10} {s : a01 ≡ a11} {t : a02 ≡ a12} + {r : a10 ≡ a11} {r′ : a11 ≡ a12} + → Square p q s r + → Square p′ s t r′ + → Square (p ∙ p′) q t (r ∙ r′) +(α ∙₂ β) i j = ((λ i → α i j) ∙ (λ i → β i j)) i + +infixr 30 _∙P_ _∙₂_ ``` ## Uniqueness @@ -1196,6 +1225,12 @@ its filler), it is contractible: → r ≡ p ∙ q ∙-unique {p = p} {q} r square i = ··-unique refl p q (_ , square) (_ , (∙-filler p q)) i .fst + +··-unique' : ∀ {ℓ} {A : Type ℓ} {w x y z : A} + → {p : w ≡ x} {q : x ≡ y} {r : y ≡ z} {s : w ≡ z} + → (β : Square (sym p) q s r) + → s ≡ p ·· q ·· r +··-unique' β i = ··-contract _ _ _ (_ , β) (~ i) .fst ``` --> @@ -1246,6 +1281,18 @@ apd : ∀ {a b} {A : I → Type a} {B : (i : I) → A i → Type b} → (p : PathP A x y) → PathP (λ i → B i (p i)) (f i0 x) (f i1 y) apd f p i = f i (p i) + +ap-square + : ∀ {ℓ ℓ′} {A : Type ℓ} {B : A → Type ℓ′} + {a00 a01 a10 a11 : A} + {p : a00 ≡ a01} + {q : a00 ≡ a10} + {s : a01 ≡ a11} + {r : a10 ≡ a11} + → (f : (a : A) → B a) + → (α : Square p q s r) + → SquareP (λ i j → B (α i j)) (ap f p) (ap f q) (ap f s) (ap f r) +ap-square f α i j = f (α i j) ``` --> @@ -1261,9 +1308,9 @@ module _ where f : A → B g : B → C - ap-comp : {x y : A} {p : x ≡ y} - → ap (λ x → g (f x)) p ≡ ap g (ap f p) - ap-comp = refl + ap-∘ : {x y : A} {p : x ≡ y} + → ap (λ x → g (f x)) p ≡ ap g (ap f p) + ap-∘ = refl ap-id : {x y : A} {p : x ≡ y} → ap (λ x → x) p ≡ p @@ -1284,12 +1331,13 @@ for the open box with sides `refl`, `ap f p` and `ap f q`, so they must be equal [uniqueness]: 1Lab.Path.html#uniqueness ```agda - ap-comp-path : (f : A → B) {x y z : A} (p : x ≡ y) (q : y ≡ z) - → ap f (p ∙ q) ≡ ap f p ∙ ap f q - ap-comp-path f p q i = ··-unique refl (ap f p) (ap f q) - (ap f (p ∙ q) , λ k j → f (∙-filler p q k j)) - (ap f p ∙ ap f q , ∙-filler _ _) - i .fst + ap-·· : (f : A → B) {x y z w : A} (p : x ≡ y) (q : y ≡ z) (r : z ≡ w) + → ap f (p ·· q ·· r) ≡ ap f p ·· ap f q ·· ap f r + ap-·· f p q r = ··-unique' (ap-square f (··-filler p q r)) + + ap-∙ : (f : A → B) {x y z : A} (p : x ≡ y) (q : y ≡ z) + → ap f (p ∙ q) ≡ ap f p ∙ ap f q + ap-∙ f p q = ap-·· f refl p q ``` # Syntax Sugar @@ -1323,7 +1371,6 @@ x ≡⟨⟩ x≡y = x≡y _∎ : ∀ {ℓ} {A : Type ℓ} (x : A) → x ≡ x x ∎ = refl -infixr 30 _∙_ _∙P_ infixr 2 _≡⟨⟩_ _≡˘⟨_⟩_ infix 3 _∎ @@ -1359,21 +1406,6 @@ your convenience, it's here too: Try pressing it! - - # Dependent Paths Surprisingly often, we want to compare inhabitants $a : A$ and $b : B$ diff --git a/src/1Lab/Path/Groupoid.lagda.md b/src/1Lab/Path/Groupoid.lagda.md index f47467456..62ff3eb7e 100644 --- a/src/1Lab/Path/Groupoid.lagda.md +++ b/src/1Lab/Path/Groupoid.lagda.md @@ -19,7 +19,7 @@ module 1Lab.Path.Groupoid where _ = Path _ = hfill _ = ap-refl -_ = ap-comp-path +_ = ap-∙ _ = ap-sym ``` --> @@ -208,7 +208,7 @@ equal to `sym (sym p)`. In that case, we show that `sym p ∙ sym (sym p) In addition to the groupoid identities for paths in a type, it has been established that functions behave like functors: These are the lemmas -`ap-refl`{.Agda}, `ap-comp-path`{.Agda} and `ap-sym`{.Agda} in the +`ap-refl`{.Agda}, `ap-∙`{.Agda} and `ap-sym`{.Agda} in the [1Lab.Path] module. [1Lab.Path]: 1Lab.Path.html#functorial-action diff --git a/src/1Lab/Path/Reasoning.lagda.md b/src/1Lab/Path/Reasoning.lagda.md index 7787df204..b427c614f 100644 --- a/src/1Lab/Path/Reasoning.lagda.md +++ b/src/1Lab/Path/Reasoning.lagda.md @@ -105,12 +105,39 @@ module _ (s≡pq : s ≡ p ∙ q) where ∙-pushr : r ∙ s ≡ (r ∙ p) ∙ q ∙-pushr = sym (∙-pullr (sym s≡pq)) + ∙→square : Square refl p s q + ∙→square = ∙-filler p q ▷ sym s≡pq + + ∙→square' : Square (sym p) q s refl + ∙→square' = ∙-filler' p q ▷ sym s≡pq + module _ (pq≡rs : p ∙ q ≡ r ∙ s) where ∙-extendl : p ∙ (q ∙ t) ≡ r ∙ (s ∙ t) ∙-extendl {t = t} = ∙-assoc _ _ _ ·· ap (_∙ t) pq≡rs ·· sym (∙-assoc _ _ _) ∙-extendr : (t ∙ p) ∙ q ≡ (t ∙ r) ∙ s ∙-extendr {t = t} = sym (∙-assoc _ _ _) ·· ap (t ∙_) pq≡rs ·· ∙-assoc _ _ _ + +··-stack : (sym p′ ·· (sym p ·· q ·· r) ·· r′) ≡ (sym (p ∙ p′) ·· q ·· (r ∙ r′)) +··-stack = ··-unique' (··-filler _ _ _ ∙₂ ··-filler _ _ _) + +··-chain : (sym p ·· q ·· r) ∙ (sym r ·· q′ ·· s) ≡ sym p ·· (q ∙ q′) ·· s +··-chain {p = p} {q = q} {r = r} {q′ = q′} {s = s} = sym (∙-unique _ square) where + square : Square refl (sym p ·· q ·· r) (sym p ·· (q ∙ q′) ·· s) (sym r ·· q′ ·· s) + square i j = hcomp (~ j ∨ (j ∧ (i ∨ ~ i))) λ where + k (k = i0) → ∙-filler q q′ i j + k (j = i0) → p k + k (j = i1) (i = i0) → r k + k (j = i1) (i = i1) → s k + +··-∙-assoc : p ·· q ·· (r ∙ s) ≡ (p ·· q ·· r) ∙ s +··-∙-assoc {p = p} {q = q} {r = r} {s = s} = sym (··-unique' square) where + square : Square (sym p) q ((p ·· q ·· r) ∙ s) (r ∙ s) + square i j = hcomp (~ i ∨ ~ j ∨ (i ∧ j)) λ where + k (k = i0) → ··-filler p q r i j + k (i = i0) → q j + k (j = i0) → p (~ i) + k (i = i1) (j = i1) → s k ``` ## Cancellation diff --git a/src/1Lab/Prelude.agda b/src/1Lab/Prelude.agda index 98d501813..cad8e643f 100644 --- a/src/1Lab/Prelude.agda +++ b/src/1Lab/Prelude.agda @@ -31,6 +31,7 @@ open import 1Lab.Univalence.SIP public open import 1Lab.Type.Pi public open import 1Lab.Type.Sigma public +open import 1Lab.Type.Pointed public open import 1Lab.HIT.Truncation public diff --git a/src/1Lab/Reflection.lagda.md b/src/1Lab/Reflection.lagda.md index f1fb984e5..edd62a037 100644 --- a/src/1Lab/Reflection.lagda.md +++ b/src/1Lab/Reflection.lagda.md @@ -6,9 +6,9 @@ open import 1Lab.Path open import 1Lab.Type hiding (absurd) open import Data.Product.NAry +open import Data.List.Base open import Data.Vec.Base open import Data.Bool -open import Data.List.Base ``` --> diff --git a/src/1Lab/Reflection/HLevel.agda b/src/1Lab/Reflection/HLevel.agda index 6c09cb642..530cbbaf2 100644 --- a/src/1Lab/Reflection/HLevel.agda +++ b/src/1Lab/Reflection/HLevel.agda @@ -9,8 +9,8 @@ open import 1Lab.Equiv open import 1Lab.Path open import 1Lab.Type -open import Data.Bool open import Data.List.Base +open import Data.Bool open import Meta.Foldable @@ -25,7 +25,7 @@ support for arbitrary level offsets (`level-minus) and searching under binders (`search-under). Ambiguity is explicitly supported: the first goal for which we can complete a proof tree is the one we go with. -The tactic works in a naÏve way, trying h-level lemmas until one +The tactic works in a naïve way, trying h-level lemmas until one succeeds. There are three ways of making progress: Using a *projection hint*, using a *decomposition hint*, or by falling back to instance selection. The instance selection fallback is self-explanatory. @@ -78,14 +78,15 @@ data Arg-spec : Type where -- lambdas. This is suitable for lemmas of type -- (∀ x y z → is-hlevel ...) → is-hlevel ... - `meta : Arg-spec - -- ^ Insert a meta at this argument position. No search will be - -- performed for this meta, so it must be solved from the context in + `term : Term → Arg-spec + -- ^ Insert a literal term at this argument position. No search will be + -- performed if this is a meta, so it must be solved from the context in -- which the lemma is used. -- Common patterns: Keep the level, search in the current scope. pattern `search = `search-under 0 pattern `level = `level-minus 0 +pattern `meta = `term unknown -- | A specification for how to decompose the type @T@ into -- sub-components, to establish an h-level result. @@ -147,7 +148,7 @@ private -- an application of is-hlevel/is-prop/is-set into an 'underlying -- type' and level arguments. hlevel-types : List Name - hlevel-types = quote is-hlevel ∷ quote is-prop ∷ quote is-set ∷ [] + hlevel-types = quote is-hlevel ∷ quote is-prop ∷ quote is-set ∷ quote is-groupoid ∷ [] pattern nat-lit n = def (quote Number.fromNat) (_ ∷ _ ∷ _ ∷ lit (nat n) v∷ _) @@ -169,6 +170,10 @@ private def (quote is-hlevel) (_ ∷ ty v∷ lv v∷ []) ← pure ty where -- Handle the ones with special names: + def (quote is-groupoid) (_ ∷ ty v∷ []) → do + ty ← wait-just-a-bit ty + pure (ty , quoteTerm 3) + def (quote is-set) (_ ∷ ty v∷ []) → do ty ← wait-just-a-bit ty pure (ty , quoteTerm 2) @@ -242,7 +247,6 @@ from the wanted level (k + n) until is-hlevel-+ n (sucᵏ′ n) w works. let's-hope = do debugPrint "tactic.hlevel" 30 $ "Lifting loop: Trying " ∷ termErr (lift-sol solution l1 it) ∷ " for level " ∷ termErr l2 ∷ [] unify goal (lift-sol solution l1 it) - -- con (quote suc) ( -- Projection decomposition. treat-as-n-type : ∀ {n} → hlevel-projection n → Term → TC ⊤ @@ -453,9 +457,7 @@ from the wanted level (k + n) until is-hlevel-+ n (sucᵏ′ n) w works. debugPrint "tactic.hlevel" 10 $ "Dunno how to take 1 from " ∷ termErr tm ∷ [] typeError [] - -- Insert a metavariable, to be solved by Agda. It'd be sad if the - -- macro handled everything! - ... | `meta = gen-args has-alts level defn args (unknown v∷ accum) cont + ... | `term t = gen-args has-alts level defn args (t v∷ accum) cont ... | `search-under under = do -- To search under some variables, we work in a scope extended @@ -558,13 +560,13 @@ from the wanted level (k + n) until is-hlevel-+ n (sucᵏ′ n) w works. decompose-is-hlevel-top goal = do ty ← withReduceDefs (false , hlevel-types) $ - (inferType goal >>= reduce) >>= wait-just-a-bit + inferType goal >>= reduce >>= wait-just-a-bit go ty where go : Term → TC _ go (pi (arg as at) (abs vn cd)) = do (inner , hlevel , enter , leave) ← go cd - pure $ inner , hlevel , extendContext vn (arg as at) , λ t → lam (ArgInfo.arg-vis as) (abs vn t) + pure $ inner , hlevel , extendContext vn (arg as at) ∘ enter , λ t → lam (ArgInfo.arg-vis as) (abs vn (leave t)) go tm = do (inner , hlevel) ← decompose-is-hlevel′ tm pure $ inner , hlevel , (λ x → x) , (λ x → x) @@ -636,6 +638,31 @@ instance decomp-lift : ∀ {ℓ ℓ′} {T : Type ℓ} → hlevel-decomposition (Lift ℓ′ T) decomp-lift = decomp (quote Lift-is-hlevel) (`level ∷ `search ∷ []) + -- h-level types themselves are propositions. These instances should be tried + -- before Π types. + + decomp-is-prop : ∀ {ℓ} {A : Type ℓ} → hlevel-decomposition (is-prop A) + decomp-is-prop = decomp (quote is-hlevel-is-hlevel-suc) (`level-minus 1 ∷ `term (quoteTerm 1) ∷ []) + + decomp-is-set : ∀ {ℓ} {A : Type ℓ} → hlevel-decomposition (is-set A) + decomp-is-set = decomp (quote is-hlevel-is-hlevel-suc) (`level-minus 1 ∷ `term (quoteTerm 2) ∷ []) + + decomp-is-groupoid : ∀ {ℓ} {A : Type ℓ} → hlevel-decomposition (is-groupoid A) + decomp-is-groupoid = decomp (quote is-hlevel-is-hlevel-suc) (`level-minus 1 ∷ `term (quoteTerm 3) ∷ []) + + {- + Since `is-prop A` starts with a Π, the decomp-piⁿ instances below could "bite" into + it and make decomp-is-prop inapplicable. To avoid this, we handle those situations explicitly: + -} + + decomp-pi²-is-prop : ∀ {ℓa ℓb ℓc} {A : Type ℓa} {B : A → Type ℓb} {C : ∀ a (b : B a) → Type ℓc} + → hlevel-decomposition (∀ a b → is-prop (C a b)) + decomp-pi²-is-prop = decomp (quote Π-is-hlevel²) (`level ∷ `search-under 2 ∷ []) + + decomp-pi-is-prop : ∀ {ℓa ℓb} {A : Type ℓa} {B : A → Type ℓb} + → hlevel-decomposition (∀ a → is-prop (B a)) + decomp-pi-is-prop = decomp (quote Π-is-hlevel) (`level ∷ `search-under 1 ∷ []) + -- -- Non-dependent Π and Σ for readability first: -- decomp-fun = decomp (quote fun-is-hlevel) (`level ∷ `search ∷ []) @@ -644,6 +671,7 @@ instance -- decomp-prod = decomp (quote ×-is-hlevel) (`level ∷ `search ∷ `search ∷ []) -- Dependent type formers: + decomp-pi³ : ∀ {ℓa ℓb ℓc ℓd} {A : Type ℓa} {B : A → Type ℓb} {C : ∀ x (y : B x) → Type ℓc} → {D : ∀ x y (z : C x y) → Type ℓd} @@ -715,4 +743,13 @@ private _ = hlevel! _ : ∀ n (x : n-Type ℓ n) → is-hlevel ∣ x ∣ (2 + n) - _ = λ n x → hlevel! + _ = hlevel! + + _ : ∀ {ℓ} {A : Type ℓ} → is-prop ((x : A) → is-prop A) + _ = hlevel! + + _ : ∀ {ℓ} {A : Type ℓ} → is-prop ((x y : A) → is-prop A) + _ = hlevel! + + _ : ∀ {ℓ} {A : Type ℓ} → is-groupoid (is-hlevel A 5) + _ = hlevel! diff --git a/src/1Lab/Reflection/Record.agda b/src/1Lab/Reflection/Record.agda index 3696d6446..0b4b9ebae 100644 --- a/src/1Lab/Reflection/Record.agda +++ b/src/1Lab/Reflection/Record.agda @@ -4,7 +4,6 @@ open import 1Lab.Equiv open import 1Lab.Path open import 1Lab.Type - import Prim.Data.Sigma as S import Prim.Data.Nat as N diff --git a/src/1Lab/Reflection/Variables.agda b/src/1Lab/Reflection/Variables.agda index 8626dfe0c..6df19d576 100644 --- a/src/1Lab/Reflection/Variables.agda +++ b/src/1Lab/Reflection/Variables.agda @@ -1,9 +1,9 @@ open import 1Lab.Reflection hiding (reverse) open import 1Lab.Type +open import Data.List.Base hiding (reverse) open import Data.Fin.Base open import Data.Nat.Base -open import Data.List.Base hiding (reverse) module 1Lab.Reflection.Variables where diff --git a/src/1Lab/Type.lagda.md b/src/1Lab/Type.lagda.md index bcbb2f1d8..0a8058ab4 100644 --- a/src/1Lab/Type.lagda.md +++ b/src/1Lab/Type.lagda.md @@ -49,6 +49,10 @@ data ⊥ : Type where absurd : ∀ {ℓ} {A : Type ℓ} → ⊥ → A absurd () + +¬_ : ∀ {ℓ} → Type ℓ → Type ℓ +¬ A = A → ⊥ +infix 3 ¬_ ``` The non-dependent product type `_×_`{.Agda} can be defined in terms of @@ -112,12 +116,5 @@ f $ₛ x = f x diff --git a/src/1Lab/Type/Pi.lagda.md b/src/1Lab/Type/Pi.lagda.md index 76395483b..5bb2b8c94 100644 --- a/src/1Lab/Type/Pi.lagda.md +++ b/src/1Lab/Type/Pi.lagda.md @@ -185,5 +185,16 @@ funext² → (∀ i j → f i j ≡ g i j) → f ≡ g funext² p i x y = p x y i + +funext-square + : ∀ {ℓ ℓ′} {A : Type ℓ} {B : A → Type ℓ′} + {f00 f01 f10 f11 : (a : A) → B a} + {p : f00 ≡ f01} + {q : f00 ≡ f10} + {s : f01 ≡ f11} + {r : f10 ≡ f11} + → (∀ a → Square (p $ₚ a) (q $ₚ a) (s $ₚ a) (r $ₚ a)) + → Square p q s r +funext-square p i j a = p a i j ``` --> diff --git a/src/1Lab/Type/Pointed.lagda.md b/src/1Lab/Type/Pointed.lagda.md new file mode 100644 index 000000000..c906ba9a2 --- /dev/null +++ b/src/1Lab/Type/Pointed.lagda.md @@ -0,0 +1,47 @@ + + +```agda +module 1Lab.Type.Pointed where +``` + +## Pointed types {defines="pointed pointed-type pointed-map pointed-homotopy"} + +A **pointed type** is a type $A$ equipped with a choice of base point $\point{A}$. + +```agda +Type∙ : ∀ ℓ → Type (lsuc ℓ) +Type∙ ℓ = Σ (Type ℓ) (λ A → A) +``` + + + +If we have pointed types $(A, a)$ and $(B, b)$, the most natural notion +of function between them is not simply the type of functions $A \to B$, +but rather those functions $A \to B$ which _preserve the basepoint_, +i.e. the functions $f : A \to B$ equipped with paths $f(a) \equiv b$. + +```agda +_→∙_ : Type∙ ℓ → Type∙ ℓ′ → Type _ +(A , a) →∙ (B , b) = Σ[ f ∈ (A → B) ] (f a ≡ b) +``` + +Paths between pointed maps are characterised as **pointed homotopies**: + +```agda +funext∙ : {f g : A →∙ B} + → (h : ∀ x → f .fst x ≡ g .fst x) + → Square (h (A .snd)) (f .snd) (g .snd) refl + → f ≡ g +funext∙ h pth i = funext h i , pth i +``` diff --git a/src/1Lab/Type/Sigma.lagda.md b/src/1Lab/Type/Sigma.lagda.md index 03ef364c0..f493a271a 100644 --- a/src/1Lab/Type/Sigma.lagda.md +++ b/src/1Lab/Type/Sigma.lagda.md @@ -208,7 +208,10 @@ into an equivalence: → {x y : Σ _ B} → (x .fst ≡ y .fst) ≃ (x ≡ y) Σ-prop-path≃ bp = Σ-prop-path bp , Σ-prop-path-is-equiv bp +``` + ## Dependent sums of contractibles diff --git a/src/1Lab/Underlying.agda b/src/1Lab/Underlying.agda index 97354cddb..f22d934d2 100644 --- a/src/1Lab/Underlying.agda +++ b/src/1Lab/Underlying.agda @@ -14,6 +14,10 @@ open Underlying ⦃ ... ⦄ using (⌞_⌟) public open Underlying using (ℓ-underlying) instance + Underlying-Type : ∀ {ℓ} → Underlying (Type ℓ) + Underlying-Type {ℓ} .ℓ-underlying = ℓ + Underlying-Type .⌞_⌟ x = x + Underlying-n-Type : ∀ {ℓ n} → Underlying (n-Type ℓ n) Underlying-n-Type {ℓ} .ℓ-underlying = ℓ Underlying-n-Type .⌞_⌟ x = ∣ x ∣ diff --git a/src/Algebra/Group/Concrete.lagda.md b/src/Algebra/Group/Concrete.lagda.md new file mode 100644 index 000000000..ffb27bc9e --- /dev/null +++ b/src/Algebra/Group/Concrete.lagda.md @@ -0,0 +1,421 @@ + + +```agda +module Algebra.Group.Concrete where +``` + + + +# Concrete groups {defines="concrete-group"} + +In homotopy type theory, we can give an alternative definition of [[groups]]: +they are the [[pointed|pointed type]], [[connected]] [[groupoids]]. +The idea is that those groupoids contain exactly the same information as their +[[fundamental group]]. + +Such groups are dubbed **concrete**, because they represent the groups of symmetries +of a given object (the base point); by opposition, "algebraic" `Group`{.Agda}s are +called **abstract**. + +```agda +record ConcreteGroup ℓ : Type (lsuc ℓ) where + no-eta-equality + constructor concrete-group + field + B : Type∙ ℓ + has-is-connected : is-connected∙ B + has-is-groupoid : is-groupoid ⌞ B ⌟ + + pt : ⌞ B ⌟ + pt = B .snd +``` + +Given a concrete group $G$, the underlying pointed type is denoted $\B{G}$, by analogy +with the [[delooping]] of an abstract group; note that, here, the delooping *is* the +chosen representation of $G$, so `B`{.Agda} is just a record field. +We write $\point{G}$ for the base point. + +Concrete groups are pointed connected types, so they enjoy the following elimination +principle, which will be useful later: + +```agda + B-elim-contr : {P : ⌞ B ⌟ → Type ℓ′} + → is-contr (P pt) + → ∀ x → P x + B-elim-contr {P = P} c = connected∙-elim-prop {P = P} has-is-connected + (is-contr→is-prop c) (c .centre) +``` + + + +A central example of a concrete group is the [[circle]]: the delooping of the [[integers]]. + +```agda +S¹-is-groupoid : is-groupoid S¹ +S¹-is-groupoid = connected∙-elim-prop S¹-is-connected hlevel! + $ connected∙-elim-prop S¹-is-connected hlevel! + $ is-hlevel≃ 2 ΩS¹≃integers (hlevel 2) + +S¹-concrete : ConcreteGroup lzero +S¹-concrete .B = S¹ , base +S¹-concrete .has-is-connected = S¹-is-connected +S¹-concrete .has-is-groupoid = S¹-is-groupoid +``` + +## The category of concrete groups + +Concrete groups naturally form a [[category]], where the morphisms are given by +[[pointed maps]] $\B{G} \to \B{H}$. + +```agda +ConcreteGroups : ∀ ℓ → Precategory (lsuc ℓ) ℓ +ConcreteGroups ℓ .Ob = ConcreteGroup ℓ +ConcreteGroups _ .Hom G H = B G →∙ B H +``` + +We immediately see one reason why the pointedness condition is needed: without it, +the morphisms between concrete groups would not form a set. + +```agda +ConcreteGroups _ .Hom-set G H (f , ptf) (g , ptg) p q = + Σ-set-square hlevel! (funext-square (B-elim-contr G square)) + where + open ConcreteGroup H using (H-Level-B) + square : is-contr ((λ j → p j .fst (pt G)) ≡ (λ j → q j .fst (pt G))) + square .centre i j = hcomp (∂ i ∨ ∂ j) λ where + k (k = i0) → pt H + k (i = i0) → p j .snd (~ k) + k (i = i1) → q j .snd (~ k) + k (j = i0) → ptf (~ k) + k (j = i1) → ptg (~ k) + square .paths _ = H .has-is-groupoid _ _ _ _ _ _ +``` + +
+ +The rest of the categorical structure is inherited from functions and paths in a +straightforward way. + + +```agda +ConcreteGroups _ .id = (λ x → x) , refl +ConcreteGroups _ ._∘_ (f , ptf) (g , ptg) = f ⊙ g , ap f ptg ∙ ptf +ConcreteGroups _ .idr f = Σ-pathp refl (∙-id-l _) +ConcreteGroups _ .idl f = Σ-pathp refl (∙-id-r _) +ConcreteGroups _ .assoc (f , ptf) (g , ptg) (h , pth) = Σ-pathp refl $ + ⌜ ap f (ap g pth ∙ ptg) ⌝ ∙ ptf ≡⟨ ap! (ap-∙ f _ _) ⟩ + (ap (f ⊙ g) pth ∙ ap f ptg) ∙ ptf ≡⟨ sym (∙-assoc _ _ _) ⟩ + ap (f ⊙ g) pth ∙ ap f ptg ∙ ptf ∎ +``` +
+ +We can check that `ConcreteGroups`{.Agda} is a [[univalent category]]: this essentially +follows from the [[univalence]] of the universe of groupoids. + + + +## Concrete vs. abstract + +Our goal is now to prove that concrete groups and abstract groups are equivalent, +in the sense that there is an [[equivalence of categories]] between `ConcreteGroups`{.Agda} +and `Groups`{.Agda}. + +To make the following developments easier, we define a version of +`πₙ₊₁ 0`{.Agda ident=πₙ₊₁} that does not use the set truncation. Indeed, there's no +need since we're dealing with groupoids: each loop space is already a set. + +```agda +π₁B : ConcreteGroup ℓ → Group ℓ +π₁B G = to-group mk where + open make-group + mk : make-group (pt G ≡ pt G) + mk .group-is-set = G .has-is-groupoid _ _ + mk .unit = refl + mk .mul = _∙_ + mk .inv = sym + mk .assoc = ∙-assoc + mk .invl = ∙-inv-l + mk .idl = ∙-id-l + +π₁≡π₀₊₁ : {G : ConcreteGroup ℓ} → π₁B G ≡ πₙ₊₁ 0 (B G) +π₁≡π₀₊₁ {G = G} = ∫-Path Groups-equational + (total-hom inc (record { pres-⋆ = λ _ _ → refl })) + (∥-∥₀-idempotent (G .has-is-groupoid _ _)) +``` + +We define a [[functor]] from concrete groups to abstract groups. +The object mapping is given by taking the `fundamental group`{.Agda ident=π₁B}. +Given a pointed map $f : \B{G} \to \B{H}$, we can `ap`{.Agda}ply it to a loop +on $\point{G}$ to get a loop on $f(\point{G})$; then, we use the fact that $f$ +is pointed to get a loop on $\point{H}$. + +```agda +Π₁ : Functor (ConcreteGroups ℓ) (Groups ℓ) +Π₁ .F₀ = π₁B +Π₁ .F₁ (f , ptf) .hom x = sym ptf ·· ap f x ·· ptf +``` + +By some simple path yoga, this preserves multiplication, and the construction is +functorial: + +```agda +Π₁ .F₁ (f , ptf) .preserves .pres-⋆ x y = + (sym ptf ·· ⌜ ap f (x ∙ y) ⌝ ·· ptf) ≡⟨ ap! (ap-∙ f _ _) ⟩ + (sym ptf ·· ap f x ∙ ap f y ·· ptf) ≡˘⟨ ··-chain ⟩ + (sym ptf ·· ap f x ·· ptf) ∙ (sym ptf ·· ap f y ·· ptf) ∎ + +Π₁ .F-id = Homomorphism-path λ _ → sym (··-filler _ _ _) +Π₁ .F-∘ (f , ptf) (g , ptg) = Homomorphism-path λ x → + (sym (ap f ptg ∙ ptf) ·· ap (f ⊙ g) x ·· (ap f ptg ∙ ptf)) ≡˘⟨ ··-stack ⟩ + (sym ptf ·· ⌜ ap f (sym ptg) ·· ap (f ⊙ g) x ·· ap f ptg ⌝ ·· ptf) ≡˘⟨ ap¡ (ap-·· f _ _ _) ⟩ + (sym ptf ·· ap f (sym ptg ·· ap g x ·· ptg) ·· ptf) ∎ +``` + +We start by showing that `Π₁`{.Agda} is [[split essentially surjective]]. This is the +easy part: to build a concrete group out of an abstract group, we simply take its +`Deloop`{.Agda}ing, and use the fact that the fundamental group of the delooping +recovers the original group. + +```agda +Π₁-is-split-eso : is-split-eso (Π₁ {ℓ}) +Π₁-is-split-eso G .fst = concrete-group (Deloop G , base) Deloop-is-connected squash +Π₁-is-split-eso G .snd = path→iso (π₁≡π₀₊₁ ∙ sym (G≡π₁B G)) +``` + +We now tackle the hard part: to prove that `Π₁`{.Agda} is [[fully faithful]]. +In order to show that the action on morphisms is an equivalence, we need a way +of "delooping" a group homomorphism $f : \pi_1(\B{G}) \to \pi_1(\B{H})$ into a +pointed map $\B{G} \to \B{H}$. + +```agda +module Deloop-Hom {G H : ConcreteGroup ℓ} (f : Groups ℓ .Hom (π₁B G) (π₁B H)) where + open ConcreteGroup H using (H-Level-B) +``` + +How can we build such a map? All we know about $\B{G}$ is that it is a pointed connected +groupoid, and thus that it comes with the elimination principle `B-elim-contr`{.Agda}. +This suggests that we need to define a type family $C : \B{G} \to \ty$ such that +$C(\point{G})$ is contractible, conclude that $\forall x. C(x)$ holds +and extract a map $\B{G} \to \B{H}$ from that. +The following construction is adapted from [@Symmetry, §4.10]: + +```agda + record C (x : ⌞ G ⌟) : Type ℓ where + constructor mk + field + y : ⌞ H ⌟ + p : pt G ≡ x → pt H ≡ y + f-p : (ω : pt G ≡ pt G) (α : pt G ≡ x) → p (ω ∙ α) ≡ f # ω ∙ p α +``` + +Our family sends a point $x : \B{G}$ to a point $y : \B{H}$ with a function $p$ that +sends based paths ending at $x$ to based paths ending at $y$, with the additional +constraint that $p$ must "extend" $f$, in the sense that a loop on the left can be +factored out using $f$. + +For the centre of contraction, we simply pick $p$ to be $f$, sending loops on +$\point{G}$ to loops on $\point{H}$. + +```agda + C-contr : is-contr (C (pt G)) + C-contr .centre .C.y = pt H + C-contr .centre .C.p = f .hom + C-contr .centre .C.f-p = f .preserves .pres-⋆ +``` + +As it turns out, such a structure is entirely determined by the pair +$(y, p(\refl) : \point{H} \equiv y)$, which means it is contractible. + +```agda + C-contr .paths (mk y p f-p) i = mk (pt≡y i) (funextP f≡p i) (□≡□ i) where + pt≡y : pt H ≡ y + pt≡y = p refl + + f≡p : ∀ ω → Square refl (f # ω) (p ω) (p refl) + f≡p ω = ∙-filler (f # ω) (p refl) ▷ (sym (f-p ω refl) ∙ ap p (∙-id-r ω)) + + □≡□ : PathP (λ i → ∀ ω α → f≡p (ω ∙ α) i ≡ f # ω ∙ f≡p α i) (f .preserves .pres-⋆) f-p + □≡□ = prop! +``` + +We can now apply the elimination principle and unpack our data: + +```agda + c : ∀ x → C x + c = B-elim-contr G C-contr + + g : B G →∙ B H + p : {x : ⌞ G ⌟} → pt G ≡ x → pt H ≡ g .fst x + + g .fst x = c x .C.y + g .snd = sym (p refl) + + p {x} = c x .C.p + + f-p : (ω : pt G ≡ pt G) (α : pt G ≡ pt G) → p (ω ∙ α) ≡ f # ω ∙ p α + f-p = c (pt G) .C.f-p +``` + +In order to show that this is a delooping of $f$ (i.e. that $\Pi_1(g) \equiv f$), +we need one more thing: that $p$ extends $g$ on the *right*. We get this essentially +for free, by path induction, because $p(α)$ ends at $g(x)$ by definition. + +```agda + p-g : (α : pt G ≡ pt G) {x' : ⌞ G ⌟} (l : pt G ≡ x') + → p (α ∙ l) ≡ p α ∙ ap (g .fst) l + p-g α = J (λ _ l → p (α ∙ l) ≡ p α ∙ ap (g .fst) l) + (ap p (∙-id-r _) ∙ sym (∙-id-r _)) +``` + +Since $g$ is pointed by $p(\refl)$, this lets us conclude that we have found a +right inverse to $\Pi_1$: + +```agda + f≡apg : (ω : pt G ≡ pt G) → Square (p refl) (f # ω) (ap (g .fst) ω) (p refl) + f≡apg ω = commutes→square $ + p refl ∙ ap (g .fst) ω ≡˘⟨ p-g refl ω ⟩ + p (refl ∙ ω) ≡˘⟨ ap p ∙-id-comm ⟩ + p (ω ∙ refl) ≡⟨ f-p ω refl ⟩ + f # ω ∙ p refl ∎ + + rinv : Π₁ .F₁ g ≡ f + rinv = Homomorphism-path λ ω → sym (··-unique' (symP (f≡apg ω))) +``` + +We are most of the way there. In order to get a proper equivalence, we must check that +delooping $\Pi_1(f)$ gives us back the same pointed map $f$. + +We use the same trick, building upon what we've done before: start by defining +a family that asserts that $p_x$ agrees with $f$ *all the way*, not just on loops: + +```agda +module Deloop-Hom-Π₁ {G H : ConcreteGroup ℓ} (f : B G →∙ B H) where + open Deloop-Hom {G = G} {H} (Π₁ .F₁ f) public + open ConcreteGroup H using (H-Level-B) + + C′ : ∀ x → Type _ + C′ x = Σ (f .fst x ≡ g .fst x) λ eq + → (α : pt G ≡ x) → Square (f .snd) (ap (f .fst) α) (p α) eq +``` + +This is a [[property]], and $\point{G}$ has it: + +```agda + C′-contr : is-contr (C′ (pt G)) + C′-contr .centre .fst = f .snd ∙ sym (g .snd) + C′-contr .centre .snd α = transport (sym Square≡double-composite-path) $ + ··-∙-assoc ∙ sym (f-p α refl) ∙ ap p (∙-id-r _) + C′-contr .paths (eq , eq-paths) = Σ-prop-path! $ + sym (∙-unique _ (transpose (eq-paths refl))) +``` + +Using the elimination principle again, we get enough information about `g` to conclude +that it is equal to `f`, so that we have a left inverse. + +```agda + c′ : ∀ x → C′ x + c′ = B-elim-contr G C′-contr + + g≡f : ∀ x → g .fst x ≡ f .fst x + g≡f x = sym (c′ x .fst) +``` + +The homotopy `g≡f` is [[pointed]] by `definition`{.Agda ident=C′-contr}, but we +need to bend the path into a `Square`{.Agda}: + +```agda + β : g≡f (pt G) ≡ sym (f .snd ∙ sym (g .snd)) + β = ap (sym ⊙ fst) (sym (C′-contr .paths (c′ (pt G)))) + + ptg≡ptf : Square (g≡f (pt G)) (g .snd) (f .snd) refl + ptg≡ptf i j = hcomp (∂ i ∨ ∂ j) λ where + k (k = i0) → ∙-filler (f .snd) (sym (g .snd)) (~ j) (~ i) + k (i = i0) → g .snd j + k (i = i1) → f .snd (j ∧ k) + k (j = i0) → β (~ k) i + k (j = i1) → f .snd (~ i ∨ k) + + linv : g ≡ f + linv = funext∙ g≡f ptg≡ptf +``` + +*Phew*. At last, `Π₁`{.Agda} is fully faithful. + +```agda +Π₁-is-ff : is-fully-faithful (Π₁ {ℓ}) +Π₁-is-ff {ℓ} {G} {H} = is-iso→is-equiv $ + iso Deloop-Hom.g Deloop-Hom.rinv (Deloop-Hom-Π₁.linv {G = G} {H}) +``` + +We've shown that `Π₁`{.Agda} is fully faithful and essentially surjective; +this lets us conclude with the desired equivalence. + +```agda +Concrete≃Abstract : is-equivalence (Π₁ {ℓ}) +Concrete≃Abstract = ff+split-eso→is-equivalence Π₁-is-ff Π₁-is-split-eso +``` diff --git a/src/Algebra/Group/Homotopy.lagda.md b/src/Algebra/Group/Homotopy.lagda.md index ab7d2ad58..ae23332d9 100644 --- a/src/Algebra/Group/Homotopy.lagda.md +++ b/src/Algebra/Group/Homotopy.lagda.md @@ -25,7 +25,7 @@ private variable ``` --> -# Homotopy Groups +# Homotopy Groups {defines="homotopy-group fundamental-group"} Given a `pointed type`{.Agda ident=Type∙} $(A, a)$ we refer to the type $a = a$ as the **loop space of $A$**, and refer to it in short as @@ -143,14 +143,14 @@ $\pi_{n+2}$ is an [[Abelian group]]: (λ x y i → inc (Ωⁿ⁺²-is-abelian-group n x y i)) ``` -## Deloopings +## Deloopings {defines="delooping"} A natural question to ask, given that all pointed types have a fundamental group, is whether every group arises as the fundamental group of some type. The answer to this question is "yes", but in the annoying way that questions like these tend to be answered: Given any -group $G$, we construct a type $B(G)$ with $\pi_1(B(G)) \equiv G$. We -call $B(G)$ the **delooping** of $G$. +group $G$, we construct a type $\B{G}$ with $\pi_1(\B{G}) \equiv G$. We +call $\B{G}$ the **delooping** of $G$. ```agda module _ {ℓ} (G : Group ℓ) where @@ -172,7 +172,7 @@ The delooping is constructed as a higher inductive type. We have a generic `base`{.Agda} point, and a constructor expressing that `Deloop`{.Agda} is a groupoid; Since it is a groupoid, it has a set of loops `point ≡ point`: this is necessary, since otherwise we would not -be able to prove that $\pi_1(B(G)) \equiv G$. We then have the +be able to prove that $\pi_1(\B{G}) \equiv G$. We then have the "interesting" higher constructors: `path`{.Agda} lets us turn any element of $G$ to a path `point ≡ point`, and `path-sq`{.Agda} expresses that `path`{.Agda} is a group homomorphism. More specifically, @@ -229,7 +229,7 @@ eliminator into propositions later, so we define that now. ```agda Deloop-elim : ∀ {ℓ'} (P : Deloop → Type ℓ') - → (∀ x → is-hlevel (P x) 3) + → (∀ x → is-groupoid (P x)) → (p : P base) → (ploop : ∀ x → PathP (λ i → P (path x i)) p p) → ( ∀ x y diff --git a/src/Algebra/Group/Homotopy/BAut.lagda.md b/src/Algebra/Group/Homotopy/BAut.lagda.md index 5e620a03a..87980c745 100644 --- a/src/Algebra/Group/Homotopy/BAut.lagda.md +++ b/src/Algebra/Group/Homotopy/BAut.lagda.md @@ -5,6 +5,8 @@ open import 1Lab.Prelude open import Algebra.Group open import Data.Set.Truncation + +open import Homotopy.Connectedness ``` --> @@ -35,12 +37,12 @@ module _ {ℓ} (T : Type ℓ) where base = T , inc (id , id-equiv) ``` -The first thing we note is that `BAut`{.Agda} is a _connected_ type, +The first thing we note is that `BAut`{.Agda} is a _[[connected]]_ type, meaning that it only has "a single point", or, more precisely, that all of its interesting information is in its (higher) path spaces: ```agda - connected : ∀ b → ∥ b ≡ base ∥ + connected : is-connected∙ (BAut , base) connected (b , x) = ∥-∥-elim {P = λ x → ∥ (b , x) ≡ base ∥} (λ _ → squash) (λ e → inc (p _ _)) x where diff --git a/src/Authors.lagda.md b/src/Authors.lagda.md index f1977b8d9..d117ef08c 100644 --- a/src/Authors.lagda.md +++ b/src/Authors.lagda.md @@ -54,9 +54,6 @@ about type theory and the implementation of programming languages, and [my personal blog]: https://amelia.how [Amulet]: https://amulet.works - -Test: [[displayed over|displayed category]] - @@ -81,7 +78,7 @@ A cool project that I recently completed was formalising a -
+
Reed he/him @@ -96,3 +93,18 @@ I like writing various forms of automation, especially those with a more semantic flavor.
+ +
+
+Naïm's profile picture +Naïm +any +monade.li +ncfavier +
+ +
+I'm Naïm. I like the [computational trilogy](https://ncatlab.org/nlab/show/computational+trilogy) +and arguing with Agda. I hate broken links and writing about myself. +
+
diff --git a/src/Cat/Allegory/Morphism.lagda.md b/src/Cat/Allegory/Morphism.lagda.md index 10b81626c..ffe4e8f15 100644 --- a/src/Cat/Allegory/Morphism.lagda.md +++ b/src/Cat/Allegory/Morphism.lagda.md @@ -1,7 +1,6 @@ diff --git a/src/Cat/Functor/Adjoint/Hom.lagda.md b/src/Cat/Functor/Adjoint/Hom.lagda.md index e4dd73267..35d856627 100644 --- a/src/Cat/Functor/Adjoint/Hom.lagda.md +++ b/src/Cat/Functor/Adjoint/Hom.lagda.md @@ -7,8 +7,6 @@ description: | -Given a monoid $M$, we build a pointed precategory $B(M)$, where the +Given a monoid $M$, we build a pointed precategory $\B{M}$, where the endomorphism monoid of the point recovers $M$. ```agda diff --git a/src/Cat/Instances/Discrete.lagda.md b/src/Cat/Instances/Discrete.lagda.md index 86ecaa57d..667ce138e 100644 --- a/src/Cat/Instances/Discrete.lagda.md +++ b/src/Cat/Instances/Discrete.lagda.md @@ -61,7 +61,7 @@ lift-disc lift-disc f .F₀ = f lift-disc f .F₁ = ap f lift-disc f .F-id = refl -lift-disc f .F-∘ p q = ap-comp-path f q p +lift-disc f .F-∘ p q = ap-∙ f q p ``` diff --git a/src/Cat/Restriction/Instances/Allegory.lagda.md b/src/Cat/Restriction/Instances/Allegory.lagda.md index b0abbe8c8..c904ab353 100644 --- a/src/Cat/Restriction/Instances/Allegory.lagda.md +++ b/src/Cat/Restriction/Instances/Allegory.lagda.md @@ -1,8 +1,8 @@ @@ -112,7 +114,7 @@ data Cofibre {ℓ ℓ′} {A : Type ℓ} {B : Type ℓ′} (f : A → B) : Type cone : ∀ a → tip ≡ base (f a) ``` -What's important here is that if a map $f$ has connected cofibre, then +What's important here is that if a map $f$ has [[connected]] cofibre, then it is a surjection --- so our proof that epis are surjective will factor through showing that epis have connected cofibres^[note that all of these types are propositions, so we have a bunch of equivalences]. @@ -120,7 +122,7 @@ these types are propositions, so we have a bunch of equivalences]. ```agda connected-cofibre→surjective : ∀ {ℓ ℓ′} {A : Type ℓ} {B : Type ℓ′} (f : A → B) - → is-contr ∥ Cofibre f ∥₀ + → is-connected (Cofibre f) → ∀ x → ∥ fibre f x ∥ connected-cofibre→surjective {A = A} {B = B} f conn x = transport cen (lift tt) where ``` @@ -169,7 +171,7 @@ inhabited), so it remains to show that any two points are merely equal. epi→connected-cofibre : ∀ {ℓ} (c d : n-Type ℓ 2) (f : ∣ c ∣ → ∣ d ∣) → Cr.is-epic (Sets ℓ) {c} {d} f - → is-contr ∥ Cofibre f ∥₀ + → is-connected (Cofibre f) epi→connected-cofibre c d f epic = contr (inc tip) $ ∥-∥₀-elim (λ _ → is-prop→is-set (squash _ _)) λ w → ∥-∥₀-path.from (hom w) diff --git a/src/Data/Set/Truncation.lagda.md b/src/Data/Set/Truncation.lagda.md index 424dd4fd0..7eacc6797 100644 --- a/src/Data/Set/Truncation.lagda.md +++ b/src/Data/Set/Truncation.lagda.md @@ -29,6 +29,14 @@ data ∥_∥₀ {ℓ} (A : Type ℓ) : Type ℓ where squash : is-set ∥ A ∥₀ ``` + + We begin by defining the induction principle. The (family of) type(s) we map into must be a set, as required by the `squash`{.Agda} constructor. diff --git a/src/HoTT.lagda.md b/src/HoTT.lagda.md index 8eb925e15..2fd46ef82 100644 --- a/src/HoTT.lagda.md +++ b/src/HoTT.lagda.md @@ -43,6 +43,7 @@ open import Data.Dec open import Data.Nat using (ℕ-well-ordered ; Discrete-Nat) open import Data.Sum +open import Homotopy.Connectedness open import Homotopy.Space.Circle open import Homotopy.Space.Torus open import Homotopy.Base @@ -103,13 +104,13 @@ _ = Ωⁿ * Lemma 2.2.1: `ap`{.Agda} * Lemma 2.2.2: - i. `ap-comp-path`{.Agda} + i. `ap-∙`{.Agda} ii. _Definitional in cubical type theory_ iii. _Definitional in cubical type theory_ iv. _Definitional in cubical type theory_ @@ -321,7 +322,8 @@ _ = Singleton-is-contr _ = equiv→is-hlevel _ = ⊎-is-hlevel _ = Σ-is-hlevel -_ = contractible-if-inhabited +_ = is-contr-if-inhabited→is-prop +_ = is-prop→is-contr-if-inhabited _ = H-Level-Dec _ = disjoint-⊎-is-prop _ = ℕ-well-ordered @@ -333,7 +335,7 @@ _ = Finite-choice * Exercise 3.1: `equiv→is-hlevel`{.Agda} * Exercise 3.2: `⊎-is-hlevel`{.Agda} * Exercise 3.3: `Σ-is-hlevel`{.Agda} -* Exercise 3.5: `contractible-if-inhabited`{.Agda} +* Exercise 3.5: `is-contr-if-inhabited→is-prop`{.Agda}, `is-prop→is-contr-if-inhabited`{.Agda} * Exercise 3.6: `H-Level-Dec`{.Agda} * Exercise 3.7: `disjoint-⊎-is-prop`{.Agda} * Exercise 3.19: `ℕ-well-ordered`{.Agda} @@ -582,6 +584,16 @@ _ = n-Tr-elim * Lemma 7.3.2: `n-Tr-elim`{.Agda} * Theorem 7.3.12: `n-Tr-path-equiv`{.Agda} +### 7.5 Connectedness + + + +* Definition 7.5.1: `is-n-connected`{.Agda} + # Part 2 Mathematics ## Chapter 8 Homotopy theory diff --git a/src/Homotopy/Base.lagda.md b/src/Homotopy/Base.lagda.md index 59ccdc5a1..778e8f5e6 100644 --- a/src/Homotopy/Base.lagda.md +++ b/src/Homotopy/Base.lagda.md @@ -20,24 +20,14 @@ module Homotopy.Base where This module contains the basic definitions for the study of synthetic homotopy theory. Synthetic homotopy theory is the name given to studying -$\infty$-groupoids in their own terms, i.e., the application of homotopy +$\infty$-groupoids in their own terms, i.e., the application of homotopy type theory to computing homotopy invariants of spaces. Central to the theory -is the concept of _pointed type_ and _pointed map_. After all, [homotopy +is the concept of [[pointed type]] and [[pointed map]]. After all, [homotopy groups] are no more than the set-truncations of n-fold iterated loop spaces, and loop spaces are always relative to a basepoint. [homotopy groups]: Algebra.Group.Homotopy.html -If we have pointed types $(A, a)$ and $(B, b)$, the most natural notion -of function between them is not simply the type of functions $A \to B$, -but rather those functions $A \to B$ which _preserve the basepoint_, -i.e. the functions $f : A \to B$ equipped with paths $f(a) \equiv b$. - -```agda -_→∙_ : ∀ {ℓ ℓ′} → Type∙ ℓ → Type∙ ℓ′ → Type _ -(A , a) →∙ (B , b) = Σ[ f ∈ (A → B) ] (f a ≡ b) -``` - A helper that will come in handy is `Σ∙`{.Agda}, which attaches the north pole as the basepoint of the suspended space. @@ -299,13 +289,15 @@ hubs-and-spokes→hlevel {A = A} (suc n) spheres x y = ``` --> +:::{.definition #truncation} Using this idea, we can define a general _$n$-truncation_ type, as a joint generalisation of the [[propositional|propositional truncation]] -and [set] truncations. While can not _directly_ build a type with a +and [set] truncations. While we can not _directly_ build a type with a constructor saying the type is $n$-truncated, what we _can_ do is freely generate `hub`{.Agda}s and `spokes`{.Agda} for any $n$-sphere drawn on -the $n$-truncation of $A$. The result is the universal $n$-type +the $n$-truncation of $A$. The result is the universal $n$-type admitting a map from $A$. +::: [set]: Data.Set.Truncation.html diff --git a/src/Homotopy/Connectedness.lagda.md b/src/Homotopy/Connectedness.lagda.md new file mode 100644 index 000000000..6a651df3a --- /dev/null +++ b/src/Homotopy/Connectedness.lagda.md @@ -0,0 +1,117 @@ + + +```agda +module Homotopy.Connectedness where +``` + +# Connectedness {defines="connected connectedness connectivity simply-connected"} + +We say that a type is **$n$-connected** if its $n$-[[truncation]] is [[contractible]]. + +While being $n$-[[truncated]] expresses that all homotopy groups above $n$ are trivial, +being $n$-connected means that all homotopy *below* $n$ are trivial. +A type that is both $n$-truncated and $n$-connected is contractible. + +We give definitions in terms of the [[propositional truncation]] and [[set truncation]] +for the lower levels, and then defer to the general "hubs and spokes" truncation. +Note that our indices are offset by 2, just like [[h-levels]]. + +```agda +is-n-connected : ∀ {ℓ} → Type ℓ → Nat → Type _ +is-n-connected A zero = Lift _ ⊤ +is-n-connected A (suc zero) = ∥ A ∥ +is-n-connected A (suc (suc zero)) = is-contr ∥ A ∥₀ +is-n-connected A n@(suc (suc (suc _))) = is-contr (n-Tr A n) +``` + +Being $n$-connected is a proposition: + +```agda +is-n-connected-is-prop : ∀ {ℓ} {A : Type ℓ} (n : Nat) → is-prop (is-n-connected A n) +is-n-connected-is-prop zero _ _ = refl +is-n-connected-is-prop (suc zero) = is-prop-∥-∥ +is-n-connected-is-prop (suc (suc zero)) = is-contr-is-prop +is-n-connected-is-prop (suc (suc (suc n))) = is-contr-is-prop +``` + +For short, we say that a type is **connected** if it is $0$-connected, and +**simply connected** if it is $1$-connected: + +```agda +is-connected : ∀ {ℓ} → Type ℓ → Type _ +is-connected A = is-n-connected A 2 + +is-simply-connected : ∀ {ℓ} → Type ℓ → Type _ +is-simply-connected A = is-n-connected A 3 +``` + +## Pointed connected types + +In the case of [[pointed types]], there is an equivalent definition of being connected +that is sometimes easier to work with: a pointed type is connected if every point is +merely equal to the base point. + +```agda +is-connected∙ : ∀ {ℓ} → Type∙ ℓ → Type _ +is-connected∙ (X , pt) = (x : X) → ∥ x ≡ pt ∥ + +module _ {ℓ} {X@(_ , pt) : Type∙ ℓ} where + is-connected∙→is-connected : is-connected∙ X → is-connected ⌞ X ⌟ + is-connected∙→is-connected c .centre = inc pt + is-connected∙→is-connected c .paths = + ∥-∥₀-elim hlevel! λ x → ∥-∥-rec! (ap inc ∘ sym) (c x) + + is-connected→is-connected∙ : is-connected ⌞ X ⌟ → is-connected∙ X + is-connected→is-connected∙ c x = + ∥-∥₀-path.to (is-contr→is-prop c (inc x) (inc pt)) +``` + +This alternative definition lets us formulate a nice elimination principle for pointed +connected types: any family of propositions $P$ that holds on the base point holds everywhere. +In particular, since `being a proposition is a proposition`{.Agda ident=is-prop-is-prop}, +we only need to check that $P(\point{})$ is a proposition. + +```agda +connected∙-elim-prop + : ∀ {ℓ ℓ′} {X : Type∙ ℓ} {P : ⌞ X ⌟ → Type ℓ′} + → is-connected∙ X + → is-prop (P (X .snd)) + → P (X .snd) + → ∀ x → P x +connected∙-elim-prop {X = X} {P} conn prop pb x = + ∥-∥-rec (P-is-prop x) (λ e → subst P (sym e) pb) (conn x) + where abstract + P-is-prop : ∀ x → is-prop (P x) + P-is-prop x = ∥-∥-rec is-prop-is-prop (λ e → subst (is-prop ∘ P) (sym e) prop) (conn x) +``` + +Examples of pointed connected types include the [[circle]] and the [[delooping]] of a group. + +```agda +S¹-is-connected : is-connected∙ (S¹ , base) +S¹-is-connected = S¹-elim (inc refl) prop! + +Deloop-is-connected : ∀ {ℓ} {G : Group ℓ} → is-connected∙ (Deloop G , base) +Deloop-is-connected = Deloop-elim-prop _ _ hlevel! (inc refl) +``` diff --git a/src/Homotopy/Space/Circle.lagda.md b/src/Homotopy/Space/Circle.lagda.md index 709e55468..797bdad16 100644 --- a/src/Homotopy/Space/Circle.lagda.md +++ b/src/Homotopy/Space/Circle.lagda.md @@ -14,7 +14,7 @@ open import Data.Int module Homotopy.Space.Circle where ``` -# Spaces: The circle +# Spaces: The circle {defines="circle"} The first example of nontrivial space one typically encounters when studying synthetic homotopy theory is the circle: it is, in a sense, the @@ -65,6 +65,15 @@ S¹-rec b l base = b S¹-rec b l (loop i) = l i ``` + + We call the map `möbius`{.Agda} a _double cover_ of the circle, since the fibre at each point is a discrete space with two elements. It has an action by the fundamental group of the circle, which has the effect of diff --git a/src/Homotopy/Space/Sphere.lagda.md b/src/Homotopy/Space/Sphere.lagda.md index 6e0c92cb2..b17d2ef92 100644 --- a/src/Homotopy/Space/Sphere.lagda.md +++ b/src/Homotopy/Space/Sphere.lagda.md @@ -114,7 +114,7 @@ using lemmas on transport in pathspaces. iso-pf .rinv base = refl iso-pf .rinv (loop i) = ap (λ p → p i) - (ap SuspS⁰→S¹ (merid N ∙ sym (merid S)) ≡⟨ ap-comp-path SuspS⁰→S¹ (merid N) (sym (merid S))⟩ + (ap SuspS⁰→S¹ (merid N ∙ sym (merid S)) ≡⟨ ap-∙ SuspS⁰→S¹ (merid N) (sym (merid S))⟩ loop ∙ refl ≡⟨ ∙-id-r loop ⟩ loop ∎) iso-pf .linv N = refl diff --git a/src/Homotopy/Space/Suspension.lagda.md b/src/Homotopy/Space/Suspension.lagda.md index 45f9388cb..c272bf6a9 100644 --- a/src/Homotopy/Space/Suspension.lagda.md +++ b/src/Homotopy/Space/Suspension.lagda.md @@ -22,7 +22,6 @@ data Susp {ℓ} (A : Type ℓ) : Type ℓ where *TODO*: Draw a picture and explain! -Suspension is an operation that increases the -[connectivity](https://ncatlab.org/nlab/show/n-connected+space) of a type; +Suspension is an operation that increases the [[connectivity]] of a type: suspending an empty type makes it inhabited, suspending an inhabited type makes it connected, suspending a connected type makes it 1-connected, etc. diff --git a/src/Meta/Bind.lagda.md b/src/Meta/Bind.lagda.md index a50b7ed55..4e56478f0 100644 --- a/src/Meta/Bind.lagda.md +++ b/src/Meta/Bind.lagda.md @@ -22,8 +22,12 @@ record Bind (M : Effect) : Typeω where _>>_ : ∀ {ℓ ℓ′} {A : Type ℓ} {B : Type ℓ′} → M.₀ A → M.₀ B → M.₀ B _>>_ f g = f >>= λ _ → g + infixl 1 _>>=_ + _=<<_ : ∀ {ℓ ℓ′} {A : Type ℓ} {B : Type ℓ′} → (A → M.₀ B) → M.₀ A → M.₀ B _=<<_ f x = x >>= f + infixr 1 _=<<_ + open Bind ⦃ ... ⦄ public ``` diff --git a/src/Order/Frame/Reasoning.lagda.md b/src/Order/Frame/Reasoning.lagda.md index 1bb1f6cc0..7a38e7dff 100644 --- a/src/Order/Frame/Reasoning.lagda.md +++ b/src/Order/Frame/Reasoning.lagda.md @@ -2,8 +2,8 @@ ```agda open import Cat.Prelude -open import Order.Diagram.Lub open import Order.Diagram.Glb +open import Order.Diagram.Lub open import Order.Semilattice open import Order.Frame open import Order.Base diff --git a/src/bibliography.bibtex b/src/bibliography.bibtex index 52e9b3b63..7ffeb15b8 100644 --- a/src/bibliography.bibtex +++ b/src/bibliography.bibtex @@ -130,3 +130,12 @@ archivePrefix={arXiv}, primaryClass={cs.LO} } + +@misc{Symmetry, + title = {Symmetry}, + author = {Marc Bezem and Ulrik Buchholtz and Pierre Cagne + and Bjørn Ian Dundas and Daniel R. Grayson}, + date = {2023-08-23}, + howpublished = {\url{https://github.com/UniMath/SymmetryBook}}, + note = {Commit: \texttt{33011eb}} +} diff --git a/src/index.lagda.md b/src/index.lagda.md index 66b91c27f..405252b5b 100644 --- a/src/index.lagda.md +++ b/src/index.lagda.md @@ -176,6 +176,7 @@ are developed under the `1Lab` namespace. Start here: -- All of these module names are links you can click! open import 1Lab.Type -- Universes +open import 1Lab.Type.Pointed -- Pointed types open import 1Lab.Path -- Path types open import 1Lab.Path.Groupoid -- Groupoid structure of types @@ -963,6 +964,7 @@ open import Algebra.Group.Cat.Base -- The category of groups open import Algebra.Group.Cat.Monadic -- ... is monadic over Sets open import Algebra.Group.Cat.FinitelyComplete -- Finite limits in Groups open import Algebra.Group.Subgroup -- Subgroups, images and kernels +open import Algebra.Group.Concrete -- Concrete groups (pointed connected groupoids) open import Algebra.Group.Homotopy -- Homotopy groups open import Algebra.Group.Homotopy.BAut @@ -988,6 +990,23 @@ open import Algebra.Ring.Module.Free -- Free R-modules as a HIT open import Algebra.Ring.Module.Category -- The bifibration of Mod over Ring ``` +# Homotopy theory + +Synthetic homotopy theory is the name given to studying +$\infty$-groupoids in their own terms, i.e., the application of homotopy type +theory to computing homotopy invariants of spaces. + +```agda +open import Homotopy.Base -- Basic definitions +open import Homotopy.Connectedness -- Connected types + +open import Homotopy.Space.Suspension -- Suspensions +open import Homotopy.Space.Circle -- The circle +open import Homotopy.Space.Sphere -- The n-spheres +open import Homotopy.Space.Sinfty -- The ∞-sphere +open import Homotopy.Space.Torus -- The torus +``` +
diff --git a/src/preamble.tex b/src/preamble.tex index 1f020ed0a..32c477ec8 100644 --- a/src/preamble.tex +++ b/src/preamble.tex @@ -73,6 +73,8 @@ \DeclareMathOperator*{\im}{im} \DeclareMathOperator*{\Sub}{Sub} \DeclareMathOperator*{\baut}{\mathbf{B}} +\newcommand{\B}[1]{\mathbf{B} #1} +\newcommand{\point}[1]{\bullet_{#1}} \DeclareMathOperator{\Lan}{Lan} \DeclareMathOperator{\Ran}{Ran} diff --git a/support/nix/nixpkgs.nix b/support/nix/nixpkgs.nix index 105027eff..26ccda5ed 100644 --- a/support/nix/nixpkgs.nix +++ b/support/nix/nixpkgs.nix @@ -1,7 +1,7 @@ -import (builtins.fetchTarball { +args: import (builtins.fetchTarball { name = "1lab-nixpkgs"; url = "https://github.com/nixos/nixpkgs/archive/cc4bb87f5457ba06af9ae57ee4328a49ce674b1b.tar.gz"; sha256 = "sha256:072q50x5p06qjf0cvz68gcrbkpv94bdl55h71j0rz6bgfhaqmiwy"; -}) { +}) ({ overlays = [ (import ./haskell-packages.nix) ]; -} +} // args) diff --git a/support/nix/node/node-dependencies.nix b/support/nix/node/node-dependencies.nix index aa5b189a6..e50ec1d34 100644 --- a/support/nix/node/node-dependencies.nix +++ b/support/nix/node/node-dependencies.nix @@ -906,8 +906,8 @@ let }; }; args = { - name = "cubical-1lab"; - packageName = "cubical-1lab"; + name = "1lab"; + packageName = "1lab"; version = "1.0.0"; src = ../../..; dependencies = [ @@ -1018,7 +1018,7 @@ let buildInputs = globalBuildInputs; meta = { description = " A formalised, cross-linked reference resource for mathematics done in Homotopy Type Theory "; - homepage = "https://github.com/plt-amy/cubical-1lab#readme"; + homepage = "https://github.com/plt-amy/1lab#readme"; license = "AGPL-3.0"; }; production = false; diff --git a/support/shake/app/Definitions.hs b/support/shake/app/Definitions.hs index 9e4382339..bb79f43d2 100644 --- a/support/shake/app/Definitions.hs +++ b/support/shake/app/Definitions.hs @@ -122,7 +122,7 @@ addDefinition key@(getMangled -> keyt) def (Glossary ge) = Glossary (go False ke Just def' | def' /= def -> error $ unlines [ "Conflict when building link map:" , "The files " ++ show (definitionModule def) ++ " and " ++ show (definitionModule def') - ++ " both define the anchor " ++ show (definitionAnchor def) + ++ " both define the term " ++ show key ] _ -> Map.insert key def{definitionCopy = c} ge diff --git a/support/sort-imports.hs b/support/sort-imports.hs index f9c119832..07295bc3f 100755 --- a/support/sort-imports.hs +++ b/support/sort-imports.hs @@ -2,6 +2,7 @@ {- stack --resolver lts-18.14 script --package text --package deepseq + --package filemanip -} {-# LANGUAGE OverloadedStrings #-} module Main where @@ -13,16 +14,22 @@ import Data.List (isSuffixOf, sortOn, groupBy, partition) import qualified Data.Text.IO as Text import qualified Data.Text as Text import Data.Function (on) -import Data.Foldable +import Data.Foldable hiding (find) import Data.Ord import Debug.Trace import System.Environment +import System.FilePath.Find import System.IO main :: IO () -main = traverse_ sortImports =<< getArgs +main = do + args <- getArgs + traverse_ sortImports =<< if null args then getAgdaFiles else pure args + +getAgdaFiles :: IO [FilePath] +getAgdaFiles = find always (fileName ~~? "*.(agda|lagda.md)") "src" sortImports :: FilePath -> IO () sortImports path @@ -81,15 +88,20 @@ sortImpl lines = sorted ++ emptyLineBefore' mod where (imports, io'') = partition ("import" `Text.isPrefixOf`) io' (opens, prefix) = partition ("open" `Text.isPrefixOf`) io'' + uniqueSortOn f = go . sortOn f where + go (x:x':xs) | x == x' = go (x':xs) + go (x:xs) = x : go xs + go [] = [] + sorted = filter (not . Text.null) prefix ++ sortItems "open import" open_imports ++ emptyLineBefore (sortItems "import" imports) - ++ emptyLineBefore (sortOn (Down . Text.length) opens) + ++ emptyLineBefore (uniqueSortOn (Down . Text.length) opens) findItem prefix line = head (Text.words (Text.drop (Text.length prefix) line)) sortItems prefix = drop 1 - . concatMap (("":) . sortOn (Down . Text.length . findItem prefix)) + . concatMap (("":) . uniqueSortOn (Down . Text.length . findItem prefix)) . groupBy ((==) `on` fst . Text.breakOn "." . findItem prefix) . sortOn (findItem prefix)