tag) with the given attributes around some HTML.
380 | anchorage :: [Attribute] -> Html -> Html
381 | anchorage attrs html = Html5.a html !! attrs
382 |
383 | -- File position anchor (unique, reliable).
384 | posAttributes :: [Attribute]
385 | posAttributes = concat
386 | [ [Attr.id $ stringValue $ show pos ]
387 | , toList $ link <$> definitionSite mi
388 | , Attr.class_ (stringValue $ unwords classes) <$ guard (not $ null classes)
389 | ]
390 |
391 | -- Named anchor (not reliable, but useful in the general case for outside refs).
392 | nameAttributes :: [Attribute]
393 | nameAttributes = [ Attr.id $ stringValue $ fromMaybe __IMPOSSIBLE__ $ mDefSiteAnchor ]
394 |
395 | classes = concat
396 | [ concatMap noteClasses (note mi)
397 | , otherAspectClasses (toList $ otherAspects mi)
398 | , concatMap aspectClasses (aspect mi)
399 | ]
400 |
401 | aspectClasses (Name mKind op) = kindClass ++ opClass
402 | where
403 | kindClass = toList $ fmap showKind mKind
404 |
405 | showKind (Constructor Inductive) = "InductiveConstructor"
406 | showKind (Constructor CoInductive) = "CoinductiveConstructor"
407 | showKind k = show k
408 |
409 | opClass = ["Operator" | op]
410 | aspectClasses a = [show a]
411 |
412 |
413 | otherAspectClasses = map show
414 |
415 | -- Notes are not included.
416 | noteClasses _s = []
417 |
418 | -- Should we output a named anchor?
419 | -- Only if we are at the definition site now (@here@)
420 | -- and such a pretty named anchor exists (see 'defSiteAnchor').
421 | hereAnchor :: Bool
422 | hereAnchor = here && isJust mDefSiteAnchor
423 |
424 | mDefinitionSite :: Maybe DefinitionSite
425 | mDefinitionSite = definitionSite mi
426 |
427 | -- Are we at the definition site now?
428 | here :: Bool
429 | here = maybe False defSiteHere mDefinitionSite
430 |
431 | mDefSiteAnchor :: Maybe String
432 | mDefSiteAnchor = maybe __IMPOSSIBLE__ defSiteAnchor mDefinitionSite
433 |
434 | link (DefinitionSite m defPos _here aName) = Attr.href $ stringValue $
435 | -- If the definition site points to the top of a file,
436 | -- we drop the anchor part and just link to the file.
437 | applyUnless (defPos <= 1)
438 | (++ "#" ++ Network.URI.Encode.encode anchor)
439 | (maybe id (>) u $ Network.URI.Encode.encode $ modToFile m "")
440 | where
441 | u = Map.lookup m moduleToURL
442 | -- Use named anchors for external links as they should be more stable(?)
443 | anchor | Just a <- aName, Just u' <- u, u' /= "" = a
444 | | otherwise = show defPos
445 |
--------------------------------------------------------------------------------
/shake/LICENSE.agda:
--------------------------------------------------------------------------------
1 | The files under HTML/ are modified versions of Agda's HTML backend.
2 | Agda is distributed with the following license:
3 |
4 | Copyright (c) 2005-2024 remains with the authors.
5 | Agda 2 was originally written by Ulf Norell,
6 | partially based on code from Agda 1 by Catarina Coquand and Makoto Takeyama,
7 | and from Agdalight by Ulf Norell and Andreas Abel.
8 | Cubical Agda was originally contributed by Andrea Vezzosi.
9 |
10 | Agda 2 is currently actively developed mainly by Andreas Abel,
11 | Guillaume Allais, Liang-Ting Chen, Jesper Cockx, Matthew Daggitt,
12 | Nils Anders Danielsson, Amélia Liao, Ulf Norell, and
13 | Andrés Sicard-Ramírez.
14 |
15 | Further, Agda 2 has received contributions by, amongst others,
16 | Arthur Adjedj, Stevan Andjelkovic,
17 | Marcin Benke, Jean-Philippe Bernardy, Guillaume Brunerie,
18 | James Chapman, Jonathan Coates,
19 | Dominique Devriese, Péter Diviánszky, Robert Estelle,
20 | Olle Fredriksson, Adam Gundry, Daniel Gustafsson, Philipp Hausmann,
21 | Alan Jeffrey, Phil de Joux,
22 | Wolfram Kahl, Wen Kokke, John Leo, Fredrik Lindblad,
23 | Víctor López Juan, Ting-Gan Lua, Francesco Mazzoli, Stefan Monnier,
24 | Guilhem Moulin, Konstantin Nisht, Fredrik Nordvall Forsberg,
25 | Josselin Poiret, Nicolas Pouillard, Jonathan Prieto, Christian Sattler,
26 | Makoto Takeyama, Andrea Vezzosi, Noam Zeilberger, and Tesla Ice Zhang.
27 | The full list of contributors is available at
28 | https://github.com/agda/agda/graphs/contributors or from the git
29 | repository via ``git shortlog -sne``.
30 |
31 | Permission is hereby granted, free of charge, to any person obtaining
32 | a copy of this software and associated documentation files (the
33 | "Software"), to deal in the Software without restriction, including
34 | without limitation the rights to use, copy, modify, merge, publish,
35 | distribute, sublicense, and/or sell copies of the Software, and to
36 | permit persons to whom the Software is furnished to do so, subject to
37 | the following conditions:
38 |
39 | The above copyright notice and this permission notice shall be
40 | included in all copies or substantial portions of the Software.
41 |
42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
43 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 |
--------------------------------------------------------------------------------
/shake/Main.hs:
--------------------------------------------------------------------------------
1 | import Agda.Compiler.Backend hiding (getEnv)
2 | import Agda.Interaction.Imports
3 | import Agda.Interaction.Library.Base
4 | import Agda.Interaction.Options
5 | import Agda.TypeChecking.Errors
6 | import Agda.Utils.FileName
7 | import Agda.Utils.Monad
8 |
9 | import Control.Monad.Error.Class
10 |
11 | import Data.Foldable
12 | import Data.List
13 | import Data.Map qualified as Map
14 | import Data.Text qualified as T
15 |
16 | import Development.Shake
17 | import Development.Shake.Classes
18 | import Development.Shake.FilePath
19 |
20 | import HTML.Backend
21 | import HTML.Base
22 |
23 | import Text.HTML.TagSoup
24 | import Text.Pandoc
25 | import Text.Pandoc.Walk
26 |
27 | newtype CompileDirectory = CompileDirectory (FilePath, FilePath)
28 | deriving (Show, Typeable, Eq, Hashable, Binary, NFData)
29 | type instance RuleResult CompileDirectory = ()
30 |
31 | sourceDir, source1labDir, buildDir, htmlDir, siteDir, everything, everything1lab :: FilePath
32 | sourceDir = "src"
33 | source1labDir = "src-1lab"
34 | buildDir = "_build"
35 | htmlDir = buildDir > "html"
36 | siteDir = buildDir > "site"
37 | everything = sourceDir > "Everything.agda"
38 | everything1lab = source1labDir > "Everything-1lab.agda"
39 |
40 | myHtmlBackend :: Backend
41 | myHtmlBackend = Backend htmlBackend'
42 | { options = initialHtmlFlags
43 | { htmlFlagDir = htmlDir
44 | , htmlFlagHighlightOccurrences = True
45 | , htmlFlagCssFile = Just "style.css"
46 | , htmlFlagHighlight = HighlightCode
47 | , htmlFlagLibToURL = \ (LibName lib version) ->
48 | let v = intercalate "." (map show version) in
49 | Map.lookup lib $ Map.fromList
50 | [ ("agda-builtins", "https://agda.github.io/agda-stdlib/master")
51 | , ("standard-library", "https://agda.github.io/agda-stdlib/v" <> v)
52 | , ("cubical", "https://agda.github.io/cubical")
53 | , ("1lab", "https://1lab.dev")
54 | , ("cubical-experiments", "")
55 | ]
56 | }
57 | }
58 |
59 | filenameToModule :: FilePath -> String
60 | filenameToModule f = dropExtensions f
61 |
62 | makeEverythingFile :: [FilePath] -> String
63 | makeEverythingFile = unlines . map (\ m -> "import " <> filenameToModule m)
64 |
65 | readFileText :: FilePath -> Action T.Text
66 | readFileText = fmap T.pack . readFile'
67 |
68 | importToModule :: String -> String
69 | importToModule s = innerText tags
70 | where tags = parseTags s
71 |
72 | patchBlock :: Block -> Block
73 | -- Add anchor links next to headers
74 | patchBlock (Header i a@(ident, _, _) inl) | ident /= "" = Header i a $
75 | inl ++ [Link ("", ["anchor"], [("aria-hidden", "true")]) [] ("#" <> ident, "")]
76 | patchBlock b = b
77 |
78 | main :: IO ()
79 | main = shakeArgs shakeOptions do
80 | -- I realise this is not how a Shakefile should be structured, but I got
81 | -- bored trying to figure it out and this is good enough for now.
82 | -- I should probably look into Development.Shake.Forward ...
83 | compileModule <- addOracle \ (CompileDirectory (sourceDir, everything)) -> do
84 | librariesFile <- getEnv "AGDA_LIBRARIES_FILE"
85 | sourceFiles <- filter (not . ("Everything*" ?==)) <$>
86 | getDirectoryFiles sourceDir ["//*.agda", "//*.lagda.md"]
87 | writeFile' everything (makeEverythingFile sourceFiles)
88 | traced "agda" do
89 | root <- absolute sourceDir
90 | runTCMTopPrettyErrors do
91 | setCommandLineOptions' root defaultOptions
92 | { optOverrideLibrariesFile = librariesFile
93 | , optDefaultLibs = False
94 | }
95 | stBackends `setTCLens` [myHtmlBackend]
96 | sourceFile <- srcFromPath =<< liftIO (absolute everything)
97 | source <- parseSource sourceFile
98 | checkResult <- typeCheckMain TypeCheck source
99 | callBackend "HTML" IsMain checkResult
100 | moduleTemplate <- readFileText "module.html"
101 | for_ sourceFiles \ sourceFile -> do
102 | let
103 | htmlFile = dropExtensions sourceFile <.> "html"
104 | literateFile = dropExtensions sourceFile <.> takeExtension sourceFile -- .lagda.md → .md
105 | contents <- case takeExtensions sourceFile of
106 | ".lagda.md" -> do
107 | markdown <- readFileText (htmlDir > literateFile)
108 | traced "pandoc" $ runIOorExplode do
109 | pandoc <- readMarkdown def {
110 | readerExtensions = foldr enableExtension pandocExtensions [Ext_autolink_bare_uris]
111 | } markdown
112 | pandoc <- pure $ walk patchBlock pandoc
113 | writeHtml5String def pandoc
114 | ".agda" -> do
115 | html <- readFileText (htmlDir > htmlFile)
116 | pure $ "" <> html <> "
"
117 | _ -> fail ("unknown extension for file " <> sourceFile)
118 | writeFile' (siteDir > htmlFile)
119 | $ T.unpack
120 | $ T.replace "@contents@" contents
121 | $ T.replace "@moduleName@" (T.pack $ filenameToModule sourceFile)
122 | $ T.replace "@path@" (T.pack $ sourceDir > sourceFile)
123 | $ moduleTemplate
124 |
125 | siteDir > "index.html" %> \ index -> do
126 | compileModule (CompileDirectory (sourceDir, everything))
127 | compileModule (CompileDirectory (source1labDir, everything1lab))
128 | indexTemplate <- readFileText "index.html"
129 | everythingAgda <- (<>)
130 | <$> readFileLines (htmlDir > "Everything.html")
131 | <*> readFileLines (htmlDir > "Everything-1lab.html")
132 | writeFile' index
133 | $ T.unpack
134 | $ T.replace "@contents@" (T.pack $ unlines $ sortOn importToModule $ everythingAgda)
135 | $ indexTemplate
136 | copyFile' "style.css" (siteDir > "style.css")
137 | copyFile' "main.js" (siteDir > "main.js")
138 | copyFile' (htmlDir > "highlight-hover.js") (siteDir > "highlight-hover.js")
139 |
140 | phony "all" do
141 | need [siteDir > "index.html"]
142 |
143 | want ["all"]
144 |
145 | runTCMTopPrettyErrors :: TCM a -> IO a
146 | runTCMTopPrettyErrors tcm = do
147 | r <- runTCMTop' $ (Just <$> tcm) `catchError` \err -> do
148 | warnings <- fmap (map show) . prettyTCWarnings' =<< getAllWarningsOfTCErr err
149 | errors <- show <$> prettyError err
150 | let everything = filter (not . null) $ warnings ++ [errors]
151 | unless (null errors) . liftIO . putStr $ unlines everything
152 | pure Nothing
153 |
154 | maybe (fail "Agda compilation failed") pure r
155 |
--------------------------------------------------------------------------------
/shake/cubical-experiments-shake.cabal:
--------------------------------------------------------------------------------
1 | cabal-version: 3.4
2 | name: cubical-experiments-shake
3 | version: 0.1.0.0
4 | license: AGPL-3.0-or-later
5 | author: Naïm Favier
6 | maintainer: n@monade.li
7 | category: Development
8 | build-type: Simple
9 |
10 | executable cubical-experiments-shake
11 | ghc-options: -Wall -Wno-name-shadowing
12 | main-is: Main.hs
13 | other-modules: HTML.Base,
14 | HTML.Backend,
15 | build-depends: base,
16 | Agda,
17 | shake,
18 | blaze-html,
19 | containers,
20 | deepseq,
21 | directory,
22 | filepath,
23 | mtl,
24 | pandoc,
25 | pandoc-types,
26 | regex-tdfa,
27 | silently,
28 | split,
29 | tagsoup,
30 | text,
31 | transformers,
32 | uri-encode,
33 | hs-source-dirs: .
34 | default-language: GHC2021
35 | default-extensions:
36 | BangPatterns
37 | BlockArguments
38 | ConstraintKinds
39 | DefaultSignatures
40 | DeriveFoldable
41 | DeriveFunctor
42 | DeriveGeneric
43 | DeriveTraversable
44 | DerivingStrategies
45 | ExistentialQuantification
46 | FlexibleContexts
47 | FlexibleInstances
48 | FunctionalDependencies
49 | GADTs
50 | GeneralizedNewtypeDeriving
51 | InstanceSigs
52 | LambdaCase
53 | MultiParamTypeClasses
54 | MultiWayIf
55 | NamedFieldPuns
56 | OverloadedStrings
57 | PatternSynonyms
58 | RankNTypes
59 | RecordWildCards
60 | ScopedTypeVariables
61 | StandaloneDeriving
62 | TupleSections
63 | TypeFamilies
64 | TypeOperators
65 | TypeSynonymInstances
66 | ViewPatterns
67 |
--------------------------------------------------------------------------------
/src-1lab/AdjunctionCommaIso.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Functor.Adjoint
2 | open import Cat.Functor.Equivalence
3 | open import Cat.Instances.Comma
4 | open import Cat.Prelude
5 |
6 | import Cat.Reasoning
7 |
8 | open ↓Hom
9 | open ↓Obj
10 | open Functor
11 | open is-iso
12 | open is-precat-iso
13 |
14 | -- An adjunction F ⊣ G induces an isomorphism of comma categories F ↓ 1 ≅ 1 ↓ G
15 | module AdjunctionCommaIso where
16 |
17 | module _
18 | {oc ℓc od ℓd} {C : Precategory oc ℓc} {D : Precategory od ℓd}
19 | {F : Functor C D} {G : Functor D C} (F⊣G : F ⊣ G)
20 | where
21 |
22 | module C = Cat.Reasoning C
23 | module D = Cat.Reasoning D
24 |
25 | to : Functor (F ↓ Id) (Id ↓ G)
26 | to .F₀ o .x = o .x
27 | to .F₀ o .y = o .y
28 | to .F₀ o .map = L-adjunct F⊣G (o .map)
29 | to .F₁ f .α = f .α
30 | to .F₁ f .β = f .β
31 | to .F₁ {a} {b} f .sq =
32 | L-adjunct F⊣G (b .map) C.∘ f .α ≡˘⟨ L-adjunct-naturall F⊣G _ _ ⟩
33 | L-adjunct F⊣G (b .map D.∘ F .F₁ (f .α)) ≡⟨ ap (L-adjunct F⊣G) (f .sq) ⟩
34 | L-adjunct F⊣G (f .β D.∘ a .map) ≡⟨ L-adjunct-naturalr F⊣G _ _ ⟩
35 | G .F₁ (f .β) C.∘ L-adjunct F⊣G (a .map) ∎
36 | to .F-id = trivial!
37 | to .F-∘ _ _ = trivial!
38 |
39 | to-is-precat-iso : is-precat-iso to
40 | to-is-precat-iso .has-is-ff = is-iso→is-equiv is where
41 | is : ∀ {a b} → is-iso (to .F₁ {a} {b})
42 | is .from f .α = f .α
43 | is .from f .β = f .β
44 | is {a} {b} .from f .sq = Equiv.injective (adjunct-hom-equiv F⊣G) $
45 | L-adjunct F⊣G (b .map D.∘ F .F₁ (f .α)) ≡⟨ L-adjunct-naturall F⊣G _ _ ⟩
46 | L-adjunct F⊣G (b .map) C.∘ f .α ≡⟨ f .sq ⟩
47 | G .F₁ (f .β) C.∘ L-adjunct F⊣G (a .map) ≡˘⟨ L-adjunct-naturalr F⊣G _ _ ⟩
48 | L-adjunct F⊣G (f .β D.∘ a .map) ∎
49 | is .rinv f = trivial!
50 | is .linv f = trivial!
51 | to-is-precat-iso .has-is-iso = is-iso→is-equiv is where
52 | is : is-iso (to .F₀)
53 | is .from o .x = o .x
54 | is .from o .y = o .y
55 | is .from o .map = R-adjunct F⊣G (o .map)
56 | is .rinv o = ↓Obj-path _ _ refl refl (L-R-adjunct F⊣G _)
57 | is .linv o = ↓Obj-path _ _ refl refl (R-L-adjunct F⊣G _)
58 |
--------------------------------------------------------------------------------
/src-1lab/Applicative.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Equiv
2 | open import 1Lab.Extensionality
3 | open import 1Lab.HLevel
4 | open import 1Lab.HLevel.Closure
5 | open import 1Lab.Path
6 | open import 1Lab.Reflection.HLevel
7 | open import 1Lab.Reflection.Record
8 | open import 1Lab.Type
9 | open import 1Lab.Type.Sigma
10 |
11 | -- Applicative fully determines the underlying Functor.
12 | module Applicative {ℓ} where
13 |
14 | private variable
15 | A B C : Type ℓ
16 |
17 | _∘'_ : ∀ {ℓ₁ ℓ₂ ℓ₃} {A : Type ℓ₁} {B : Type ℓ₂} {C : Type ℓ₃}
18 | → (B → C) → (A → B) → A → C
19 | f ∘' g = λ z → f (g z)
20 |
21 | record applicative (F : Type ℓ → Type ℓ) : Type (lsuc ℓ) where
22 | infixl 8 _<*>_
23 | field
24 | sets : is-set (F A)
25 | pure : A → F A
26 | _<*>_ : F (A → B) → F A → F B
27 | <*>-identity : ∀ {u : F A}
28 | → pure id <*> u ≡ u
29 | <*>-composition : ∀ {u : F (B → C)} {v : F (A → B)} {w : F A}
30 | → pure _∘'_ <*> u <*> v <*> w ≡ u <*> (v <*> w)
31 | <*>-homomorphism : ∀ {f : A → B} {x : A}
32 | → pure f <*> pure x ≡ pure (f x)
33 | <*>-interchange : ∀ {u : F (A → B)} {x : A}
34 | → u <*> pure x ≡ pure (λ f → f x) <*> u
35 |
36 | record applicative-functor (F : Type ℓ → Type ℓ) (app : applicative F) : Type (lsuc ℓ) where
37 | open applicative app
38 | infixl 8 _<$>_
39 | field
40 | _<$>_ : (A → B) → F A → F B
41 | <$>-identity : ∀ {x : F A}
42 | → id <$> x ≡ x
43 | <$>-composition : ∀ {f : B → C} {g : A → B} {x : F A}
44 | → f <$> (g <$> x) ≡ f ∘' g <$> x
45 | pure-natural : ∀ {f : A → B} {x : A}
46 | → f <$> pure x ≡ pure (f x)
47 | <*>-extranatural-A : ∀ {f : F (B → C)} {g : A → B} {x : F A}
48 | → f <*> (g <$> x) ≡ (_∘' g) <$> f <*> x
49 | <*>-natural-B : ∀ {g : B → C} {f : F (A → B)} {x : F A}
50 | → g <$> (f <*> x) ≡ (g ∘'_) <$> f <*> x
51 |
52 | open applicative-functor
53 | unquoteDecl eqv = declare-record-iso eqv (quote applicative-functor)
54 |
55 | applicative-functor-path
56 | : ∀ {F : Type ℓ → Type ℓ} {app} {a b : applicative-functor F app}
57 | → (∀ {A B} (f : A → B) x → a ._<$>_ f x ≡ b ._<$>_ f x)
58 | → a ≡ b
59 | applicative-functor-path {F = F} {app = app} p = Iso.injective eqv (Σ-prop-path! (ext λ f → p f))
60 | where instance
61 | F-sets : ∀ {x} → H-Level (F x) 2
62 | F-sets = hlevel-instance (app .applicative.sets)
63 |
64 | applicative-determines-functor : ∀ {F} (app : applicative F)
65 | → is-contr (applicative-functor F app)
66 | applicative-determines-functor {F} app = p where
67 | open applicative app
68 | p : is-contr (applicative-functor F app)
69 | p .centre ._<$>_ f x = pure f <*> x
70 | p .centre .<$>-identity = <*>-identity
71 | p .centre .<$>-composition {f = f} {g = g} {x = x} =
72 | pure f <*> (pure g <*> x) ≡⟨ sym <*>-composition ⟩
73 | pure _∘'_ <*> pure f <*> pure g <*> x ≡⟨ ap (λ y → y <*> pure g <*> x) <*>-homomorphism ⟩
74 | pure (f ∘'_) <*> pure g <*> x ≡⟨ ap (_<*> x) <*>-homomorphism ⟩
75 | pure (f ∘' g) <*> x ∎
76 | p .centre .pure-natural = <*>-homomorphism
77 | p .centre .<*>-extranatural-A {f = f} {g = g} {x = x} =
78 | f <*> (pure g <*> x) ≡⟨ sym <*>-composition ⟩
79 | pure _∘'_ <*> f <*> pure g <*> x ≡⟨ ap (_<*> x) <*>-interchange ⟩
80 | pure (_$ g) <*> (pure _∘'_ <*> f) <*> x ≡⟨ ap (_<*> x) (p .centre .<$>-composition) ⟩
81 | pure (_∘' g) <*> f <*> x ∎
82 | p .centre .<*>-natural-B {g = g} {f = f} {x = x} =
83 | pure g <*> (f <*> x) ≡⟨ sym <*>-composition ⟩
84 | pure _∘'_ <*> pure g <*> f <*> x ≡⟨ ap (λ y → y <*> f <*> x) <*>-homomorphism ⟩
85 | pure (g ∘'_) <*> f <*> x ∎
86 | p .paths app' = applicative-functor-path λ f x →
87 | pure f <*> x ≡⟨ ap (_<*> x) (sym A.pure-natural) ⟩
88 | (f ∘'_) A.<$> pure id <*> x ≡˘⟨ A.<*>-natural-B ⟩
89 | f A.<$> (pure id <*> x) ≡⟨ ap (f A.<$>_) <*>-identity ⟩
90 | f A.<$> x ∎
91 | where module A = applicative-functor app'
92 |
--------------------------------------------------------------------------------
/src-1lab/CoherentlyConstant.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude hiding (∥_∥³; ∥-∥³-elim-set; ∥-∥³-elim-prop; ∥-∥³-rec; ∥-∥³-is-prop; ∥-∥-rec-groupoid)
2 | open import 1Lab.Path.Reasoning
3 |
4 | -- Coherently constant maps into groupoids, now at https://1lab.dev/1Lab.HIT.Truncation.html#maps-into-groupoids
5 | module CoherentlyConstant where
6 |
7 | data ∥_∥³ {ℓ} (A : Type ℓ) : Type ℓ where
8 | inc : A → ∥ A ∥³
9 | iconst : ∀ a b → inc a ≡ inc b
10 | icoh : ∀ a b c → PathP (λ i → inc a ≡ iconst b c i) (iconst a b) (iconst a c)
11 | squash : is-groupoid ∥ A ∥³
12 |
13 | ∥-∥³-elim-set
14 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ∥ A ∥³ → Type ℓ'}
15 | → (∀ a → is-set (P a))
16 | → (f : (a : A) → P (inc a))
17 | → (∀ a b → PathP (λ i → P (iconst a b i)) (f a) (f b))
18 | → ∀ a → P a
19 | ∥-∥³-elim-set {P = P} sets f fconst = go where
20 | go : ∀ a → P a
21 | go (inc x) = f x
22 | go (iconst a b i) = fconst a b i
23 | go (icoh a b c i j) = is-set→squarep (λ i j → sets (icoh a b c i j))
24 | refl (λ i → go (iconst a b i)) (λ i → go (iconst a c i)) (λ i → go (iconst b c i))
25 | i j
26 | go (squash a b p q r s i j k) = is-hlevel→is-hlevel-dep 2 (λ _ → is-hlevel-suc 2 (sets _))
27 | (go a) (go b)
28 | (λ k → go (p k)) (λ k → go (q k))
29 | (λ j k → go (r j k)) (λ j k → go (s j k))
30 | (squash a b p q r s) i j k
31 |
32 | ∥-∥³-elim-prop
33 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ∥ A ∥³ → Type ℓ'}
34 | → (∀ a → is-prop (P a))
35 | → (f : (a : A) → P (inc a))
36 | → ∀ a → P a
37 | ∥-∥³-elim-prop props f = ∥-∥³-elim-set (λ _ → is-hlevel-suc 1 (props _)) f
38 | (λ _ _ → is-prop→pathp (λ _ → props _) _ _)
39 |
40 | ∥-∥³-rec
41 | : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
42 | → is-groupoid B
43 | → (f : A → B)
44 | → (fconst : ∀ x y → f x ≡ f y)
45 | → (∀ x y z → fconst x y ∙ fconst y z ≡ fconst x z)
46 | → ∥ A ∥³ → B
47 | ∥-∥³-rec {A = A} {B} bgrpd f fconst fcoh = go where
48 | go : ∥ A ∥³ → B
49 | go (inc x) = f x
50 | go (iconst a b i) = fconst a b i
51 | go (icoh a b c i j) = ∙→square (sym (fcoh a b c)) i j
52 | go (squash x y a b p q i j k) = bgrpd
53 | (go x) (go y)
54 | (λ i → go (a i)) (λ i → go (b i))
55 | (λ i j → go (p i j)) (λ i j → go (q i j))
56 | i j k
57 |
58 | ∥-∥³-is-prop : ∀ {ℓ} {A : Type ℓ} → is-prop ∥ A ∥³
59 | ∥-∥³-is-prop = is-contr-if-inhabited→is-prop $
60 | ∥-∥³-elim-prop (λ _ → hlevel 1)
61 | (λ a → contr (inc a) (∥-∥³-elim-set (λ _ → squash _ _) (iconst a) (icoh a)))
62 |
63 | ∥-∥-rec-groupoid
64 | : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
65 | → is-groupoid B
66 | → (f : A → B)
67 | → (fconst : ∀ x y → f x ≡ f y)
68 | → (∀ x y z → fconst x y ∙ fconst y z ≡ fconst x z)
69 | → ∥ A ∥ → B
70 | ∥-∥-rec-groupoid bgrpd f fconst fcoh =
71 | ∥-∥³-rec bgrpd f fconst fcoh ∘ ∥-∥-rec ∥-∥³-is-prop inc
72 |
--------------------------------------------------------------------------------
/src-1lab/EasyParametricity.lagda.md:
--------------------------------------------------------------------------------
1 |
2 | Imports
3 |
4 | ```agda
5 | open import Cat.Prelude hiding (J)
6 | open import Cat.Diagram.Limit.Base
7 | open import Cat.Instances.Discrete
8 | open import Cat.Instances.Shape.Join
9 | open import Cat.Instances.Product
10 |
11 | open import Data.Sum
12 |
13 | import Cat.Reasoning
14 | import Cat.Functor.Reasoning
15 | import Cat.Functor.Bifunctor
16 |
17 | open Precategory
18 | open Functor
19 | open make-is-limit
20 | ```
21 |
22 |
23 | This module formalises a few very interesting results from Jem Lord's recent work on
24 | [*Easy Parametricity*](https://hott-uf.github.io/2025/abstracts/HoTTUF_2025_paper_21.pdf),
25 | presented at [HoTT/UF 2025](https://hott-uf.github.io/2025/).
26 |
27 | ```agda
28 | module EasyParametricity {u} where
29 |
30 | U = Type u
31 | 𝟘 = Lift u ⊥
32 | 𝟙 = Lift u ⊤
33 |
34 | -- We think of functions f : U → A as "bridges" from f 𝟘 to f 𝟙.
35 | record Bridge {ℓ} (A : Type ℓ) (x y : A) : Type (ℓ ⊔ lsuc u) where
36 | no-eta-equality
37 | constructor bridge
38 | pattern
39 | field
40 | app : U → A
41 | app𝟘 : app 𝟘 ≡ x
42 | app𝟙 : app 𝟙 ≡ y
43 |
44 | -- Every function preserves bridges.
45 | ap-bridge
46 | : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} (f : A → B) {x y : A}
47 | → Bridge A x y → Bridge B (f x) (f y)
48 | ap-bridge f (bridge app app𝟘 app𝟙) = bridge (f ⊙ app) (ap f app𝟘) (ap f app𝟙)
49 |
50 | postulate
51 | -- An immediate consequence of Jem Lord's parametricity axiom: a function
52 | -- out of U into a U-small type cannot tell 0 and 1 apart; this is all we need here.
53 | -- In other words, U-small types are bridge-discrete.
54 | parametricity : ∀ {A : U} {x y : A} → Bridge A x y → x ≡ y
55 |
56 | -- The type of formal composites r ∘ l : A → B in C. We want to think of this
57 | -- as the type of factorisations of some morphism f : A → B, but it turns out
58 | -- to be unnecessary to track f in the type.
59 | record Factorisation {o ℓ} (C : Precategory o ℓ) (A B : C .Ob) : Type (o ⊔ ℓ) where
60 | constructor factor
61 | module C = Precategory C
62 | field
63 | X : C.Ob
64 | l : C.Hom A X
65 | r : C.Hom X B
66 |
67 | module _
68 | {o ℓ} {C : Precategory o ℓ}
69 | (let module C = Precategory C)
70 | where
71 |
72 | module _ {A B : C.Ob} (f : C.Hom A B) where
73 |
74 | -- The two factorisations id ∘ f and f ∘ id.
75 | _∘id id∘_ : Factorisation C A B
76 | _∘id = factor A C.id f
77 | id∘_ = factor B f C.id
78 |
79 | module _
80 | (C-complete : is-complete u lzero C)
81 | (C-category : is-category C)
82 | {A B : C.Ob} (f : C.Hom A B)
83 | where
84 |
85 | -- In a U-complete univalent category, every type of factorisations is bridge-codiscrete.
86 | -- We define a bridge from id ∘ f to f ∘ id.
87 |
88 | factorisation-bridge : Bridge (Factorisation C A B) (id∘ f) (f ∘id)
89 | factorisation-bridge = bridge b b0 b1 where
90 |
91 | b : U → Factorisation C A B
92 | b P = fac (C-complete diagram) module b where
93 |
94 | -- This is the interesting part: given a type P : U, we construct the
95 | -- wide pullback of P-many copies of f.
96 | -- Since we only care about the cases where P is a proposition, we
97 | -- can just take the discrete or codiscrete category on P and adjoin a
98 | -- terminal object to get our diagram shape.
99 | J : Precategory u lzero
100 | J = Codisc' P ▹
101 |
102 | diagram : Functor J C
103 | diagram .F₀ (inl _) = A
104 | diagram .F₀ (inr _) = B
105 | diagram .F₁ {inl _} {inl _} _ = C.id
106 | diagram .F₁ {inl _} {inr _} _ = f
107 | diagram .F₁ {inr _} {inr _} _ = C.id
108 | diagram .F-id {inl _} = refl
109 | diagram .F-id {inr _} = refl
110 | diagram .F-∘ {inl _} {inl _} {inl _} _ _ = sym (C.idl _)
111 | diagram .F-∘ {inl _} {inl _} {inr _} _ _ = sym (C.idr _)
112 | diagram .F-∘ {inl _} {inr _} {inr _} _ _ = sym (C.idl _)
113 | diagram .F-∘ {inr _} {inr _} {inr _} _ _ = sym (C.idl _)
114 |
115 | -- Given a limit of this diagram (which exists by the assumption of U-completeness),
116 | -- we get a factorisation of f as the universal map followed by the projection to B.
117 | fac : Limit diagram → Factorisation C A B
118 | fac lim = factor X l r where
119 | module lim = Limit lim
120 | X : C.Ob
121 | X = lim.apex
122 | l : C.Hom A X
123 | l = lim.universal (λ { (inl _) → C.id; (inr _) → f }) λ where
124 | {inl _} {inl _} _ → C.idl _
125 | {inl _} {inr _} _ → C.idr _
126 | {inr _} {inr _} _ → C.idl _
127 | r : C.Hom X B
128 | r = lim.cone ._=>_.η (inr tt)
129 |
130 | -- We check that the endpoints of the bridge are what we expect: when P
131 | -- is empty, we are taking the limit of the single-object diagram B, so
132 | -- our factorisation is A → B → B.
133 | b0 : b 𝟘 ≡ id∘ f
134 | b0 = ap (b.fac 𝟘) (Limit-is-prop C-category (C-complete _) (to-limit lim)) where
135 | lim : is-limit (b.diagram 𝟘) B _
136 | lim = to-is-limit λ where
137 | .ψ (inr _) → C.id
138 | .commutes {inr _} {inr _} _ → C.idl _
139 | .universal eps comm → eps (inr _)
140 | .factors {inr _} eps comm → C.idl _
141 | .unique eps comm other fac → sym (C.idl _) ∙ fac (inr _)
142 |
143 | -- When P is contractible, we are taking the limit of the arrow diagram
144 | -- A → B, so our factorisation is A → A → B.
145 | b1 : b 𝟙 ≡ f ∘id
146 | b1 = ap (b.fac 𝟙) (Limit-is-prop C-category (C-complete _) (to-limit lim)) where
147 | lim : is-limit (b.diagram 𝟙) A _
148 | lim = to-is-limit λ where
149 | .ψ (inl _) → C.id
150 | .ψ (inr _) → f
151 | .commutes {inl _} {inl _} _ → C.idl _
152 | .commutes {inl _} {inr _} _ → C.idr _
153 | .commutes {inr _} {inr _} _ → C.idl _
154 | .universal eps comm → eps (inl (lift tt))
155 | .factors {inl _} eps comm → C.idl _
156 | .factors {inr _} eps comm → comm {inl _} {inr _} _
157 | .unique eps comm other fac → sym (C.idl _) ∙ fac (inl _)
158 |
159 | -- Theorem 1: let C be a U-complete univalent category and D a locally
160 | -- U-small category.
161 | module _
162 | {o o' ℓ} {C : Precategory o ℓ} {D : Precategory o' u}
163 | (let module C = Cat.Reasoning C) (let module D = Cat.Reasoning D)
164 | (C-complete : is-complete u lzero C)
165 | (C-category : is-category C)
166 | where
167 |
168 | -- 1.a: naturality of transformations between functors C → D is free.
169 | -- (This is a special case of 1.b.)
170 | module _
171 | (F G : Functor C D)
172 | (let module F = Cat.Functor.Reasoning F) (let module G = Cat.Functor.Reasoning G)
173 | (η : ∀ x → D.Hom (F.₀ x) (G.₀ x))
174 | where
175 |
176 | natural : is-natural-transformation F G η
177 | natural A B f = G.introl refl ∙ z0≡z1 ∙ (D.refl⟩∘⟨ F.elimr refl) where
178 |
179 | -- Given a factorisation A → X → B, we define the map
180 | -- F A
181 | -- ↓
182 | -- η X : F X → G X
183 | -- ↓
184 | -- G B
185 | -- which recovers the naturality square for f as the factorisation varies
186 | -- from id ∘ f to f ∘ id.
187 | z : Factorisation C A B → D.Hom (F.₀ A) (G.₀ B)
188 | z (factor X l r) = G.₁ r D.∘ η X D.∘ F.₁ l
189 |
190 | -- As a result, we get a bridge from one side of the naturality square
191 | -- to the other; since D is locally U-small, the Hom-sets of D are bridge-discrete,
192 | -- so we get the desired equality.
193 | z0≡z1 : z (id∘ f) ≡ z (f ∘id)
194 | z0≡z1 = parametricity (ap-bridge z (factorisation-bridge C-complete C-category f))
195 |
196 | -- 1.b: dinaturality of transformations between bifunctors C^op × C → D is free.
197 | module _
198 | (F G : Functor (C ^op ×ᶜ C) D)
199 | (let module F = Cat.Functor.Bifunctor F) (let module G = Cat.Functor.Bifunctor G)
200 | (η : ∀ x → D.Hom (F.₀ (x , x)) (G.₀ (x , x)))
201 | where
202 |
203 | dinatural
204 | : ∀ A B (f : C.Hom A B)
205 | → G.first f D.∘ η B D.∘ F.second f ≡ G.second f D.∘ η A D.∘ F.first f
206 | dinatural A B f = z0≡z1 where
207 |
208 | -- Given a factorisation A → X → B, we define the map
209 | -- F B A → F X X → G X X → G A B
210 | -- which interpolates between the two sides of the dinaturality hexagon.
211 | z : Factorisation C A B → D.Hom (F.₀ (B , A)) (G.₀ (A , B))
212 | z (factor X l r) = G.₁ (l , r) D.∘ η X D.∘ F.₁ (r , l)
213 |
214 | z0≡z1 : z (id∘ f) ≡ z (f ∘id)
215 | z0≡z1 = parametricity (ap-bridge z (factorisation-bridge C-complete C-category f))
216 | ```
217 |
--------------------------------------------------------------------------------
/src-1lab/ErasureOpen.lagda.md:
--------------------------------------------------------------------------------
1 | ```agda
2 | open import 1Lab.Prelude hiding (map)
3 | open import 1Lab.Reflection.Induction
4 | ```
5 |
6 | Investigating the fact that Agda's erasure modality is an open modality.
7 | Terminology is borrowed and some proofs are extracted from the paper
8 | [Modalities in homotopy type theory](https://arxiv.org/abs/1706.07526)
9 | by Rijke, Shulman and Spitters.
10 | The erasure modality was previously investigated in
11 | [Logical properties of a modality for erasure](https://www.cse.chalmers.se/~nad/publications/danielsson-erased.pdf)
12 | by Danielsson.
13 |
14 | ```agda
15 | module ErasureOpen where
16 |
17 | private variable
18 | ℓ ℓ' : Level
19 | A B : Type ℓ
20 | ```
21 |
22 | ## Erasure as an open modality
23 |
24 | The `Erased` monadic modality, internalising `@0`:
25 |
26 | ```agda
27 | record Erased (@0 A : Type ℓ) : Type ℓ where
28 | constructor [_]
29 | field
30 | @0 erased : A
31 |
32 | open Erased
33 |
34 | η : {@0 A : Type ℓ} → A → Erased A
35 | η x = [ x ]
36 |
37 | μ : {@0 A : Type ℓ} → Erased (Erased A) → Erased A
38 | μ [ [ x ] ] = [ x ]
39 | ```
40 |
41 | ...is equivalent to the **open** modality `○` induced by the following subsingleton:
42 |
43 | ```agda
44 | data Compiling : Type where
45 | @0 compiling : Compiling
46 |
47 | Compiling-is-prop : is-prop Compiling
48 | Compiling-is-prop compiling compiling = refl
49 |
50 | ○_ : Type ℓ → Type ℓ
51 | ○ A = Compiling → A
52 |
53 | ○'_ : ○ Type ℓ → Type ℓ
54 | ○' A = (c : Compiling) → A c
55 |
56 | infix 30 ○_ ○'_
57 |
58 | ○→Erased : ○ A → Erased A
59 | ○→Erased a .erased = a compiling
60 |
61 | -- Agda considers clauses that match on erased constructors as erased.
62 | Erased→○ : Erased A → ○ A
63 | Erased→○ a compiling = a .erased
64 |
65 | ○≃Erased : ○ A ≃ Erased A
66 | ○≃Erased = Iso→Equiv (○→Erased ,
67 | iso Erased→○ (λ _ → refl) (λ _ → funext λ where compiling → refl))
68 |
69 | η○ : A → ○ A
70 | η○ a _ = a
71 | ```
72 |
73 | Since Agda allows erased matches for the empty type, the empty type is
74 | modal; in other words, we are not not `Compiling`.
75 |
76 | ```agda
77 | ¬¬compiling : ¬ ¬ Compiling
78 | ¬¬compiling ¬c with ○→Erased ¬c
79 | ... | ()
80 | ```
81 |
82 | ## Open and closed modalities
83 |
84 | The corresponding **closed** modality `●` is given by the join with `Compiling`,
85 | which is equivalent to the following higher inductive type.
86 |
87 | ```agda
88 | data ●_ (A : Type ℓ) : Type ℓ where
89 | -- At runtime, we only have A.
90 | η● : A → ● A
91 | -- At compile time, we also have an erased "cone" that glues all of A together,
92 | -- so that ● A is contractible.
93 | @0 tip : ● A
94 | @0 cone : (a : A) → η● a ≡ tip
95 |
96 | infix 30 ●_
97 |
98 | unquoteDecl ●-elim = make-elim ●-elim (quote ●_)
99 |
100 | @0 ●-contr : is-contr (● A)
101 | ●-contr {A = A} = contr tip λ a → sym (ps a) where
102 | ps : (a : ● A) → a ≡ tip
103 | ps = ●-elim cone refl λ a i j → cone a (i ∨ j)
104 | ```
105 |
106 | The rest of this file investigates some properties of open and closed
107 | modalities that are not specific to the `Compiling` proposition we use here.
108 |
109 |
110 | Some common definitions about higher modalities
111 |
112 | ```agda
113 | module Modality
114 | {○_ : ∀ {ℓ} → Type ℓ → Type ℓ}
115 | (η○ : ∀ {ℓ} {A : Type ℓ} → A → ○ A)
116 | (○-elim : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ○ A → Type ℓ'}
117 | → ((a : A) → ○ P (η○ a)) → (a : ○ A) → ○ P a)
118 | (○-elim-β : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ○ A → Type ℓ'} {pη : (a : A) → ○ P (η○ a)}
119 | → (a : A) → ○-elim {P = P} pη (η○ a) ≡ pη a)
120 | (○-≡-modal : ∀ {ℓ} {A : Type ℓ} {x y : ○ A} → is-equiv (η○ {A = x ≡ y}))
121 | where
122 |
123 | modal : Type ℓ → Type ℓ
124 | modal A = is-equiv (η○ {A = A})
125 |
126 | modal-map : (A → B) → Type _
127 | modal-map {B = B} f = (b : B) → modal (fibre f b)
128 |
129 | connected : Type ℓ → Type ℓ
130 | connected A = is-contr (○ A)
131 |
132 | connected-map : (A → B) → Type _
133 | connected-map {B = B} f = (b : B) → connected (fibre f b)
134 |
135 | modal+connected→contr : modal A → connected A → is-contr A
136 | modal+connected→contr A-mod A-conn = Equiv→is-hlevel 0 (η○ , A-mod) A-conn
137 |
138 | modal+connected→equiv : {f : A → B} → modal-map f → connected-map f → is-equiv f
139 | modal+connected→equiv f-mod f-conn .is-eqv b = modal+connected→contr (f-mod b) (f-conn b)
140 |
141 | elim-modal
142 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ○ A → Type ℓ'}
143 | → (∀ a → modal (P a))
144 | → ((a : A) → P (η○ a)) → (a : ○ A) → P a
145 | elim-modal P-modal pη a = equiv→inverse (P-modal a) (○-elim (λ a → η○ (pη a)) a)
146 |
147 | elim-modal-β
148 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ○ A → Type ℓ'} P-modal {pη : (a : A) → P (η○ a)}
149 | → (a : A) → elim-modal {P = P} P-modal pη (η○ a) ≡ pη a
150 | elim-modal-β P-modal {pη} a =
151 | ap (equiv→inverse (P-modal (η○ a))) (○-elim-β a)
152 | ∙ equiv→unit (P-modal (η○ a)) (pη a)
153 |
154 | map : (A → B) → ○ A → ○ B
155 | map f = ○-elim (η○ ∘ f)
156 |
157 | map-≃ : A ≃ B → (○ A) ≃ (○ B)
158 | map-≃ e = map (e .fst) , is-iso→is-equiv λ where
159 | .is-iso.from → map (Equiv.from e)
160 | .is-iso.rinv → elim-modal (λ _ → ○-≡-modal) λ b →
161 | ap (map (e .fst)) (○-elim-β b) ∙ ○-elim-β (Equiv.from e b) ∙ ap η○ (Equiv.ε e b)
162 | .is-iso.linv → elim-modal (λ _ → ○-≡-modal) λ a →
163 | ap (map (Equiv.from e)) (○-elim-β a) ∙ ○-elim-β (e .fst a) ∙ ap η○ (Equiv.η e a)
164 |
165 | retract-○→modal : (η⁻¹ : ○ A → A) → is-left-inverse η⁻¹ η○ → modal A
166 | retract-○→modal η⁻¹ ret = is-iso→is-equiv $
167 | iso η⁻¹ (elim-modal (λ _ → ○-≡-modal) λ a → ap η○ (ret a)) ret
168 |
169 | retract→modal
170 | : (f : A → B) (g : B → A)
171 | → is-left-inverse f g → modal A → modal B
172 | retract→modal {B = B} f g ret A-modal = retract-○→modal η⁻¹ linv where
173 | η⁻¹ : ○ B → B
174 | η⁻¹ = f ∘ elim-modal (λ _ → A-modal) g
175 | linv : is-left-inverse η⁻¹ η○
176 | linv b = ap f (elim-modal-β (λ _ → A-modal) b) ∙ ret b
177 |
178 | modal-≃ : B ≃ A → modal A → modal B
179 | modal-≃ e = retract→modal (Equiv.from e) (Equiv.to e) (Equiv.η e)
180 |
181 | connected-≃ : B ≃ A → connected A → connected B
182 | connected-≃ e A-conn = Equiv→is-hlevel 0 (map-≃ e) A-conn
183 |
184 | ≡-modal : modal A → ∀ {x y : A} → modal (x ≡ y)
185 | ≡-modal A-modal = modal-≃ (ap-equiv (η○ , A-modal)) ○-≡-modal
186 |
187 | PathP-modal : {A : I → Type ℓ} → modal (A i0) → ∀ {x y} → modal (PathP A x y)
188 | PathP-modal {A = A} A-modal {x} {y} = subst modal (sym (PathP≡Path⁻ A x y)) (≡-modal A-modal)
189 |
190 | reflection-modal : modal (○ A)
191 | reflection-modal = is-iso→is-equiv λ where
192 | .is-iso.from → ○-elim id
193 | .is-iso.rinv → elim-modal (λ _ → ○-≡-modal) λ a → ap η○ (○-elim-β a)
194 | .is-iso.linv → ○-elim-β
195 |
196 | Π-modal : {B : A → Type ℓ} → (∀ a → modal (B a)) → modal ((a : A) → B a)
197 | Π-modal B-modal = retract-○→modal
198 | (λ f a → elim-modal (λ _ → B-modal _) (_$ a) f)
199 | (λ f → funext λ a → elim-modal-β (λ _ → B-modal _) f)
200 |
201 | Σ-modal : {B : A → Type ℓ} → modal A → (∀ a → modal (B a)) → modal (Σ A B)
202 | Σ-modal {B = B} A-modal B-modal = retract-○→modal
203 | (Equiv.from Σ-Π-distrib
204 | ( elim-modal (λ _ → A-modal) fst
205 | , elim-modal (λ _ → B-modal _) λ (a , b) →
206 | subst B (sym (elim-modal-β (λ _ → A-modal) (a , b))) b))
207 | λ (a , b) →
208 | elim-modal-β (λ _ → A-modal) (a , b)
209 | ,ₚ elim-modal-β (λ _ → B-modal _) (a , b) ◁ to-pathp⁻ refl
210 |
211 | η-connected : connected-map (η○ {A = A})
212 | η-connected a = contr
213 | (○-elim {P = fibre η○} (λ a → η○ (a , refl)) a)
214 | (elim-modal (λ _ → ○-≡-modal) λ (a' , p) →
215 | J (λ a p → ○-elim (λ x → η○ (x , refl)) a ≡ η○ (a' , p)) (○-elim-β a') p)
216 |
217 | ○Σ○≃○Σ : {B : A → Type ℓ} → (○ (Σ A λ a → ○ B a)) ≃ (○ (Σ A B))
218 | ○Σ○≃○Σ .fst = ○-elim λ (a , b) → map (a ,_) b
219 | ○Σ○≃○Σ .snd = is-iso→is-equiv λ where
220 | .is-iso.from → map (Σ-map₂ η○)
221 | .is-iso.rinv → elim-modal (λ _ → ○-≡-modal) λ (a , b) →
222 | ap (○-elim _) (○-elim-β (a , b)) ∙ ○-elim-β (a , η○ b) ∙ ○-elim-β b
223 | .is-iso.linv → elim-modal (λ _ → ○-≡-modal) λ (a , b) →
224 | ap (map _) (○-elim-β (a , b)) ∙ elim-modal
225 | {P = λ b → ○-elim _ (○-elim _ b) ≡ η○ (a , b)} (λ _ → ○-≡-modal)
226 | (λ b → ap (○-elim _) (○-elim-β b) ∙ ○-elim-β (a , b)) b
227 |
228 | Σ-connected : {B : A → Type ℓ} → connected A → (∀ a → connected (B a)) → connected (Σ A B)
229 | Σ-connected A-conn B-conn = Equiv→is-hlevel 0 (○Σ○≃○Σ e⁻¹)
230 | (connected-≃ (Σ-contract B-conn) A-conn)
231 |
232 | -- Additional properties of *lex* modalities
233 |
234 | module _ (○-lex : ∀ {ℓ} {A : Type ℓ} {a b : A} → (○ (a ≡ b)) ≃ (η○ a ≡ η○ b)) where
235 | ≡-connected : connected A → {x y : A} → connected (x ≡ y)
236 | ≡-connected A-conn = Equiv→is-hlevel 0 ○-lex (Path-is-hlevel 0 A-conn)
237 |
238 | PathP-connected : {A : I → Type ℓ} → connected (A i0) → ∀ {x y} → connected (PathP A x y)
239 | PathP-connected {A = A} A-conn {x} {y} =
240 | subst connected (sym (PathP≡Path⁻ A x y)) (≡-connected A-conn)
241 | ```
242 |
243 |
244 | `○` and `●` are higher modalities, so we can instantiate this module
245 | for both of them.
246 |
247 | ```agda
248 | ○-elim-○
249 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ○ A → Type ℓ'}
250 | → ((a : A) → ○ P (η○ a)) → (a : ○ A) → ○ P a
251 | ○-elim-○ {P = P} pη a c =
252 | subst P (funext λ _ → ap a (Compiling-is-prop _ _)) (pη (a c) c)
253 |
254 | ○-≡-modal : {x y : ○ A} → is-equiv (η○ {A = x ≡ y})
255 | ○-≡-modal = is-iso→is-equiv λ where
256 | .is-iso.from p i compiling → p compiling i compiling
257 | .is-iso.rinv p i compiling j compiling → p compiling j compiling
258 | .is-iso.linv p i j compiling → p j compiling
259 |
260 | ●-elim-●
261 | : ∀ {ℓ ℓ'} {A : Type ℓ} {P : ● A → Type ℓ'}
262 | → ((a : A) → ● P (η● a)) → (a : ● A) → ● P a
263 | ●-elim-● pη = ●-elim pη tip λ _ → is-contr→pathp (λ _ → ●-contr) _ _
264 |
265 | ●-≡-modal : {x y : ● A} → is-equiv (η● {A = x ≡ y})
266 | ●-≡-modal = is-iso→is-equiv λ where
267 | .is-iso.from → ●-elim id (is-contr→is-prop ●-contr _ _)
268 | λ p → is-contr→is-set ●-contr _ _ _ _
269 | .is-iso.rinv → ●-elim (λ _ → refl) (sym (●-contr .paths _))
270 | λ p → is-set→squarep (λ _ _ → is-contr→is-set ●-contr) _ _ _ _
271 | .is-iso.linv _ → refl
272 |
273 | module ○ = Modality η○ ○-elim-○ (λ _ → funext λ _ → transport-refl _) ○-≡-modal
274 | module ● = Modality η● ●-elim-● (λ _ → refl) ●-≡-modal
275 | ```
276 |
277 | Open and closed modalities are lex.
278 |
279 | ```agda
280 | ○-lex : {a b : A} → ○ (a ≡ b) ≃ (η○ a ≡ η○ b)
281 | ○-lex = funext≃
282 |
283 | module ●-ids {A : Type ℓ} {a : A} where
284 | code : ● A → Type ℓ
285 | code = ●-elim (λ b → ● (a ≡ b)) (Lift _ ⊤) (λ b → ua (is-contr→≃ ●-contr (hlevel 0)))
286 |
287 | code-refl : code (η● a)
288 | code-refl = η● refl
289 |
290 | decode : ∀ b → code b → η● a ≡ b
291 | decode = ●.elim-modal (λ _ → ●.Π-modal λ _ → ●-≡-modal)
292 | λ a → ●.elim-modal (λ _ → ●-≡-modal) (ap η●)
293 |
294 | decode-over : ∀ b (c : code b) → PathP (λ i → code (decode b c i)) code-refl c
295 | decode-over = ●.elim-modal (λ _ → ●.Π-modal λ _ → ●.PathP-modal ●.reflection-modal)
296 | λ a → ●.elim-modal (λ _ → ●.PathP-modal ●.reflection-modal)
297 | λ p i → η● λ j → p (i ∧ j)
298 |
299 | ids : is-based-identity-system (η● a) code code-refl
300 | ids .to-path {b} = decode b
301 | ids .to-path-over {b} = decode-over b
302 |
303 | ●-lex : {a b : A} → ● (a ≡ b) ≃ (η● a ≡ η● b)
304 | ●-lex = based-identity-system-gives-path ●-ids.ids
305 | ```
306 |
307 | Some equivalences specific to open and closed modalities:
308 |
309 |
310 | `●-modal A ≃ ○ (is-contr A) ≃ is-contr (○ A) = ○-connected A`
311 |
312 |
313 | ```agda
314 | @0 ●-modal→contr : ●.modal A → is-contr A
315 | ●-modal→contr A-modal = Equiv→is-hlevel 0 (η● , A-modal) ●-contr
316 |
317 | contr→●-modal : @0 is-contr A → ●.modal A
318 | contr→●-modal A-contr = ●.retract-○→modal
319 | (●-elim id (A-contr .centre) λ a → sym (A-contr .paths a))
320 | λ _ → refl
321 |
322 | contr→○-connected : @0 is-contr A → ○.connected A
323 | contr→○-connected A-contr = contr (Erased→○ [ A-contr .centre ]) λ a →
324 | funext λ where compiling → A-contr .paths _
325 |
326 | @0 ○-connected→contr : ○.connected A → is-contr A
327 | ○-connected→contr A-conn = contr (A-conn .centre compiling) λ a →
328 | A-conn .paths (η○ a) $ₚ compiling
329 |
330 | ○-connected→●-modal : ○.connected A → ●.modal A
331 | ○-connected→●-modal A-conn = contr→●-modal (○-connected→contr A-conn)
332 | ```
333 |
334 | ## Artin gluing
335 |
336 | We prove an **Artin gluing** theorem: every type `A` is equivalent to a
337 | certain pullback of `○ A` and `● A` over `● ○ A`, which we call `Fracture A`.
338 | Handwaving, this corresponds to decomposing a type into its "compile time"
339 | part and its "runtime" part.
340 |
341 | ```agda
342 | ○→●○ : ○ A → ● ○ A
343 | ○→●○ = η●
344 |
345 | ●→●○ : ● A → ● ○ A
346 | ●→●○ = ●.map η○
347 |
348 | Fracture : Type ℓ → Type ℓ
349 | Fracture A = Σ (○ A × ● A) λ (o , c) → ○→●○ o ≡ ●→●○ c
350 |
351 | module _ {A : Type ℓ} where
352 | fracture : A → Fracture A
353 | fracture a = (η○ a , η● a) , refl
354 | ```
355 |
356 | The idea is to prove that the fibres of the `fracture` map are both
357 | `●`-modal and `●`-connected, and hence contractible.
358 |
359 | For the modal part, we observe that an element of the fibre of `fracture`
360 | at a triple `(o : ○ A, c : ● A, p)` can be rearranged into an element
361 | of the fibre of `η○` at `o` (which is `○`-connected, hence `●`-modal) together with
362 | a dependent path whose type is `●`-modal by standard results about higher modalities.
363 |
364 | ```agda
365 | fracture-modal : ●.modal-map fracture
366 | fracture-modal ((o , c) , p) = ●.modal-≃ e $
367 | ●.Σ-modal (○-connected→●-modal (○.η-connected _)) λ _ →
368 | ●.PathP-modal $ ●.Σ-modal ●.reflection-modal λ _ → ●-≡-modal
369 | where
370 | e : fibre fracture ((o , c) , p)
371 | ≃ Σ (fibre η○ o) λ (a , q) →
372 | PathP (λ i → Σ (● A) λ c → ○→●○ (q i) ≡ ●→●○ c) (η● a , refl) (c , p)
373 | e = Σ-ap-snd (λ _ → ap-equiv (Σ-assoc e⁻¹) ∙e Σ-pathp≃ e⁻¹) ∙e Σ-assoc
374 | ```
375 |
376 | Almost symmetrically, for the connected part, we rearrange the fibre
377 | into an element of the fibre of `η●` at `c` (which is `●`-connected) together
378 | with a dependent path in the fibres of `○→●○`. Since the latter is
379 | defined as `η●` its fibres are `●`-connected as well, hence the path type
380 | is `●`-connected because `●` is lex.
381 |
382 | ```agda
383 | fracture-connected : ●.connected-map fracture
384 | fracture-connected ((o , c) , p) = ●.connected-≃ e $
385 | ●.Σ-connected (●.η-connected _) λ _ →
386 | ●.PathP-connected ●-lex (●.η-connected _)
387 | where
388 | e : fibre fracture ((o , c) , p)
389 | ≃ Σ (fibre η● c) λ (a , q) →
390 | PathP (λ i → Σ (○ A) λ o → ○→●○ o ≡ ●→●○ (q i)) (η○ a , refl) (o , p)
391 | e = Σ-ap-snd (λ _ → ap-equiv (Σ-ap-fst ×-swap ∙e Σ-assoc e⁻¹) ∙e Σ-pathp≃ e⁻¹) ∙e Σ-assoc
392 |
393 | fracture-is-equiv : is-equiv fracture
394 | fracture-is-equiv = ●.modal+connected→equiv fracture-modal fracture-connected
395 |
396 | Artin-gluing : A ≃ Fracture A
397 | Artin-gluing = fracture , fracture-is-equiv
398 | ```
399 |
--------------------------------------------------------------------------------
/src-1lab/FirstGroupCohomology.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Path.Reasoning
2 | open import 1Lab.Prelude
3 |
4 | open import Algebra.Group.Cat.Base
5 | open import Algebra.Group.Concrete
6 | open import Algebra.Group.Ab
7 |
8 | open import Cat.Prelude
9 |
10 | open import Homotopy.Space.Delooping
11 |
12 | -- This now lives at https://1lab.dev/Algebra.Group.Concrete.Abelian.html#first-abelian-group-cohomology
13 | module FirstGroupCohomology where
14 |
15 | open Precategory
16 |
17 | π₁BG≡G : ∀ {ℓ} (G : Group ℓ) → π₁B (Concrete G) ≡ G
18 | π₁BG≡G G = π₁B≡π₀₊₁ (Concrete G) ∙ sym (G≡π₁B G)
19 |
20 | -- Any two loops commute in the delooping of an abelian group.
21 | ab→square : ∀ {ℓ} {H : Group ℓ} (H-ab : is-commutative-group H)
22 | → {x : Deloop H} (p q : x ≡ x) → Square p q q p
23 | ab→square {H = H} H-ab {x} = Deloop-elim-prop H (λ x → (p q : x ≡ x) → Square p q q p) (λ _ → hlevel 1)
24 | (λ p q → commutes→square (subst is-commutative-group (sym (π₁BG≡G H)) H-ab p q)) x
25 |
26 | module _ {ℓ} (G : Group ℓ) (H : Group ℓ) (H-ab : is-commutative-group H) where
27 | -- The first cohomology of G with coefficients in H.
28 | -- We will show that it is equivalent to the set of group homomorphisms from G
29 | -- to H, assuming that H is abelian.
30 | H¹[G,H] = ∥ (Deloop G → Deloop H) ∥₀
31 |
32 | unpoint : (Deloop∙ G →∙ Deloop∙ H) → H¹[G,H]
33 | unpoint (f , _) = inc f
34 |
35 | work : ∀ f → f base ≡ base → is-contr (fibre unpoint (inc f))
36 | work f ptf .centre = (f , ptf) , refl
37 | work f ptf .paths ((g , ptg) , g≡f) = Σ-prop-path! (Σ-pathp
38 | (funext (Deloop-elim-set G _ (λ _ → hlevel 2) (ptf ∙ sym ptg) λ z → rec!
39 | (λ g≡f → J
40 | (λ g _ → ∀ ptg → Square (ap f (path z)) (ptf ∙ sym ptg) (ptf ∙ sym ptg) (ap g (path z)))
41 | (λ _ → ab→square H-ab _ _)
42 | (sym g≡f) ptg)
43 | (∥-∥₀-path.to g≡f)))
44 | (flip₂ (∙-filler'' ptf (sym ptg))))
45 |
46 | unpoint-is-equiv : is-equiv unpoint
47 | unpoint-is-equiv .is-eqv = ∥-∥₀-elim (λ _ → hlevel 2)
48 | λ f → rec! (work f) (Deloop-is-connected (f base))
49 |
50 | unpoint≃ : H¹[G,H] ≃ (Deloop∙ G →∙ Deloop∙ H)
51 | unpoint≃ = (unpoint , unpoint-is-equiv) e⁻¹
52 |
53 | delooping : (Deloop∙ G →∙ Deloop∙ H) ≃ Hom (Groups ℓ) (π₁B (Concrete G)) (π₁B (Concrete H))
54 | delooping = _ , π₁F-is-ff {_} {Concrete G} {Concrete H}
55 |
56 | first-group-cohomology : H¹[G,H] ≃ Hom (Groups ℓ) G H
57 | first-group-cohomology = unpoint≃ ∙e delooping
58 | ∙e path→equiv (ap₂ (Hom (Groups ℓ)) (π₁BG≡G G) (π₁BG≡G H))
59 |
60 | -- As a cool application, the space of endomorphisms of the delooping of ℤ/2ℤ has
61 | -- exactly two connected components!
62 | -- (But note that there is no type with exactly two endomorphisms: it would be a set,
63 | -- and nⁿ = 2 has no integer solutions.)
64 |
--------------------------------------------------------------------------------
/src-1lab/Goat.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 | open import Data.Dec
3 | open import Data.Nat
4 |
5 | {-
6 | A formalisation of https://en.wikipedia.org/wiki/Wolf,_goat_and_cabbage_problem
7 | to demonstrate proof by reflection.
8 | -}
9 | module Goat where
10 |
11 | holds : ∀ {ℓ} (A : Type ℓ) ⦃ _ : Dec A ⦄ → Type
12 | holds _ ⦃ yes _ ⦄ = ⊤
13 | holds _ ⦃ no _ ⦄ = ⊥
14 |
15 | data Side : Type where
16 | left right : Side
17 |
18 | left≠right : ¬ left ≡ right
19 | left≠right p = subst (λ { left → ⊤; right → ⊥ }) p tt
20 |
21 | instance
22 | Discrete-Side : Discrete Side
23 | Discrete-Side {left} {left} = yes refl
24 | Discrete-Side {left} {right} = no left≠right
25 | Discrete-Side {right} {left} = no (left≠right ∘ sym)
26 | Discrete-Side {right} {right} = yes refl
27 |
28 | cross : Side → Side
29 | cross left = right
30 | cross right = left
31 |
32 | record State : Type where
33 | constructor state
34 | field
35 | farmer wolf goat cabbage : Side
36 |
37 | open State
38 |
39 | count-left : Side → Nat
40 | count-left left = 1
41 | count-left right = 0
42 | count-lefts : State → Nat
43 | count-lefts (state f w g c) = count-left f + count-left w + count-left g + count-left c
44 |
45 | is-valid : State → Type
46 | is-valid s@(state f w g c) = count-lefts s ≡ 2 → f ≡ g
47 |
48 | record Valid-state : Type where
49 | constructor valid
50 | field
51 | has-state : State
52 | ⦃ has-valid ⦄ : holds (is-valid has-state)
53 |
54 | open Valid-state
55 |
56 | data Move : State → State → Type where
57 | go-alone : ∀ {s} → Move s (record s { farmer = cross (s .farmer) })
58 | take-wolf : ∀ {s} → Move s (record s { farmer = cross (s .farmer); wolf = cross (s .wolf) })
59 | take-goat : ∀ {s} → Move s (record s { farmer = cross (s .farmer); goat = cross (s .goat) })
60 | take-cabbage : ∀ {s} → Move s (record s { farmer = cross (s .farmer); cabbage = cross (s .cabbage) })
61 |
62 | data Moves : Valid-state → Valid-state → Type where
63 | done : ∀ {s} → Moves s s
64 | _∷_ : ∀ {a b c} ⦃ _ : holds (is-valid b) ⦄ → Move (a .has-state) b → Moves (valid b) c → Moves a c
65 |
66 | infixr 6 _∷_
67 |
68 | initial final : Valid-state
69 | initial = valid (state left left left left)
70 | final = valid (state right right right right)
71 |
72 | goal : Moves initial final
73 | goal = take-goat ∷ go-alone ∷ take-wolf ∷ take-goat ∷ take-cabbage ∷ go-alone ∷ take-goat ∷ done
74 | -- goal = {! take-wolf ∷ ? !} -- No instance of type holds (is-valid ...) was found in scope.
75 |
--------------------------------------------------------------------------------
/src-1lab/Hats.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Path.Reasoning
2 | open import 1Lab.Prelude
3 |
4 | open import Algebra.Monoid.Category
5 | open import Algebra.Group
6 |
7 | open import Data.List hiding (lookup)
8 | open import Data.Fin
9 | open import Data.Fin.Closure
10 |
11 | open is-iso
12 |
13 | {-
14 | This is a formalisation of a hat puzzle whose statement you can read at any
15 | of these places:
16 |
17 | https://www.jsoftware.com/pipermail/general/2007-June/030272.html
18 | https://www.cut-the-knot.org/blue/PuzzleWithHats.shtml
19 | https://twitter.com/gro_tsen/status/1618989823100096512
20 |
21 | 🎩 SPOILERS AHEAD! 🎩
22 | -}
23 | module Hats where
24 |
25 | -- We assume there's at least one person, and that everyone has a unique
26 | -- "name" between 0 and n - 1, known to everyone else.
27 | module _ (n-1 : Nat) where
28 | private
29 | n = suc n-1
30 | Person = Fin n
31 | Hat = Fin n
32 | Hats = Person → Hat
33 |
34 | record Strategy : Type where
35 | -- `guess i xs` is the guess made by the ith person upon seeing the n - 1
36 | -- other hats given by `xs` (a vector of numbers from 0 to n - 1).
37 | field
38 | guess : Person → (Fin n-1 → Hat) → Hat
39 |
40 | -- The relation `hats ✓ i` means that the ith person guesses correctly,
41 | -- given the assignment `hats`.
42 | _✓_ : Hats → Person → Type
43 | hats ✓ i = guess i (delete hats i) ≡ hats i
44 |
45 | -- We are interested in strategies where at least one person guesses
46 | -- correctly for every assignment of hats.
47 | field
48 | one-right : ∀ hats → Σ Person λ i → hats ✓ i
49 |
50 | -- First, note that, given this requirement, there can be at *most* one
51 | -- correct guess for every assignment of hats.
52 | -- This follows from a probabilistic argument: every person guesses correctly
53 | -- with probability 1/n, so the total number of correct guesses across all
54 | -- hat assignments is nⁿ.
55 | -- In order to conclude, we use the fact that any surjection between finite
56 | -- sets of equal cardinality is an equivalence.
57 | exactly-one-right : ∀ hats → is-contr (Σ Person λ i → hats ✓ i)
58 | exactly-one-right hats = Equiv→is-hlevel 0 (Fibre-equiv _ hats e⁻¹) (p-is-equiv .is-eqv hats)
59 | where
60 | probability : ∀ i → Iso (Σ Hats (_✓ i)) (Fin n-1 → Hat)
61 | probability i .fst (hats , _) = delete hats i
62 | probability i .snd .from other .fst = other [ i ≔ guess i other ]
63 | probability i .snd .from other .snd =
64 | guess i ⌜ delete (other [ i ≔ guess i other ]) i ⌝ ≡⟨ ap! (funext (delete-insert _ i _)) ⟩
65 | guess i other ≡˘⟨ insert-lookup _ i _ ⟩
66 | (other [ i ≔ guess i other ]) i ∎
67 | probability i .snd .rinv _ = funext (delete-insert _ i _)
68 | probability i .snd .linv (hats , r) = Σ-prop-path! (funext (insert-delete _ i _ (sym r)))
69 |
70 | only-one : Σ Hats (λ hats → Σ Person (hats ✓_)) ≃ Hats
71 | only-one =
72 | Σ _ (λ hats → Σ _ λ i → hats ✓ i) ≃⟨ Σ-swap₂ ⟩
73 | Σ _ (λ i → Σ _ λ hats → hats ✓ i) ≃⟨ Σ-ap-snd (Iso→Equiv ∘ probability) ⟩
74 | Fin n × (Fin n-1 → Fin n) ≃˘⟨ Fin-suc-Π ⟩
75 | (Fin n → Fin n) ≃∎
76 |
77 | p : Σ Hats (λ hats → Σ Person (hats ✓_)) → Hats
78 | p = fst
79 | p-is-equiv : is-equiv p
80 | p-is-equiv = Finite-surjection→equiv (inc only-one) p
81 | λ other → inc ((other , one-right other) , refl)
82 |
83 | open Strategy public
84 |
85 | -- n-hypercubes of order m. We won't use the extra degree of generality,
86 | -- but it doesn't hurt.
87 | Hypercube : Nat → Type
88 | Hypercube m = (Fin n → Fin m) → Fin m
89 |
90 | -- Latin hypercubes, or n-ary quasigroups.
91 | -- Every number appears exactly once on each "line"; equivalently,
92 | -- every partial application to n - 1 coordinates is an automorphism.
93 | is-latin : ∀ {m} → Hypercube m → Type
94 | is-latin {m} h = ∀ (i : Fin n) (xs : Fin n-1 → Fin m) → is-equiv λ x → h (xs [ i ≔ x ])
95 |
96 | Latin-hypercube : Nat → Type
97 | Latin-hypercube m = Σ (Hypercube m) is-latin
98 |
99 | -- Every latin n-hypercube h of order n induces a strategy where everyone
100 | -- guesses that the multiplication of all the hats is equal to their index.
101 | latin→strategy : Latin-hypercube n → Strategy
102 | latin→strategy (h , lat) .guess i other = equiv→inverse (lat i other) i
103 | latin→strategy (h , lat) .one-right hats =
104 | h hats , Equiv.from (eqv (h hats)) refl
105 | where
106 | module L i = Equiv (_ , lat i (delete hats i))
107 | eqv : ∀ (i : Fin n) → (L.from i i ≡ hats i) ≃ (h hats ≡ i)
108 | eqv i =
109 | L.from i i ≡ hats i ≃⟨ Equiv.adjunct (L.inverse i) ⟩
110 | i ≡ L.to i (hats i) ≃⟨ sym-equiv ⟩
111 | L.to i (hats i) ≡ i ≃⟨ ∙-pre-equiv (sym (ap h (funext (insert-delete hats i _ refl)))) ⟩
112 | h hats ≡ i ≃∎
113 |
114 | -- In particular, every group structure on Fin n induces a strategy since
115 | -- group multiplication is an n-ary equivalence.
116 | group→latin : Group-on (Fin n) → Latin-hypercube n
117 | group→latin G = mul , mul-equiv
118 | where
119 | open Group-on G hiding (magma-hlevel)
120 |
121 | mul : ∀ {m} → (Fin m → Fin n) → Fin n
122 | mul xs = fold underlying-monoid (tabulate xs)
123 |
124 | mul-equiv : ∀ {m} (i : Fin (suc m)) (xs : Fin m → Fin n)
125 | → is-equiv (λ x → mul (xs [ i ≔ x ]))
126 | mul-equiv i xs with fin-view i
127 | mul-equiv _ xs | zero = ⋆-equivr _
128 | mul-equiv {suc m} _ xs | suc i = ∘-is-equiv (mul-equiv i (xs ∘ fsuc)) (⋆-equivl _)
129 |
130 | group→strategy : Group-on (Fin n) → Strategy
131 | group→strategy = latin→strategy ∘ group→latin
132 |
--------------------------------------------------------------------------------
/src-1lab/Madeleine.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 | open import 1Lab.Classical
3 | open import Data.Sum
4 | open import Data.Dec
5 | open import Data.Bool
6 | open import Meta.Invariant
7 |
8 | module Madeleine where
9 |
10 | axiom = ∀ {ℓ} {P Q : Type ℓ} ⦃ _ : H-Level P 1 ⦄ ⦃ _ : H-Level Q 1 ⦄ → ∥ P ⊎ Q ∥ → P ⊎ Q
11 |
12 | lem→axiom : LEM → axiom
13 | lem→axiom lem {P = P} {Q} pq with lem (elΩ P)
14 | ... | yes a = inl (□-out! a)
15 | ... | no ¬a = inr (rec! (λ { (inl p) → absurd (¬a (inc p)); (inr q) → q }) pq)
16 |
17 | module _ (ε : axiom) where
18 |
19 | module _ {ℓ} {X : Type ℓ} ⦃ _ : H-Level X 2 ⦄ (a₀ a₁ : X) where
20 | E : X → Type _
21 | E x = (a₀ ≡ x) ⊎ (a₁ ≡ x)
22 |
23 | E' : Type _
24 | E' = Σ X λ x → ∥ E x ∥
25 |
26 | r : Bool → E'
27 | r true = a₀ , inc (inl refl)
28 | r false = a₁ , inc (inr refl)
29 |
30 | s : E' → Bool
31 | s (x , e) with ε e
32 | ... | inl _ = true
33 | ... | inr _ = false
34 |
35 | r-s : ∀ e → r (s e) ≡ e
36 | r-s (x , e) with ε e
37 | ... | inl p = Σ-prop-path! p
38 | ... | inr p = Σ-prop-path! p
39 |
40 | discrete : Dec (a₀ ≡ a₁)
41 | discrete = invmap
42 | (λ p → ap fst (right-inverse→injective r r-s p))
43 | (λ p → ap s (Σ-prop-path! p))
44 | (s (r true) ≡? s (r false))
45 |
46 | lem : LEM
47 | lem P = invmap (λ p → subst ∣_∣ (sym p) _) (λ p → Ω-ua _ (λ _ → p))
48 | (discrete P ⊤Ω)
49 |
--------------------------------------------------------------------------------
/src-1lab/MonoidalFibres.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 | open import Homotopy.Connectedness
3 | open import Cat.Prelude
4 | open import Cat.Functor.Base
5 | open import Cat.Functor.Properties
6 |
7 | -- eso + full-on-isos functors have monoidal fibres.
8 | module MonoidalFibres where
9 |
10 | private variable
11 | o ℓ : Level
12 | C D : Precategory o ℓ
13 |
14 | monoidal-fibres
15 | : ∀ {F : Functor C D}
16 | → is-category C → is-category D
17 | → is-eso F → is-full-on-isos F
18 | → ∀ y → is-connected (Essential-fibre F y)
19 | monoidal-fibres {D = D} {F = F} ccat dcat eso full≅ y =
20 | case eso y of λ y′ Fy′≅y → is-connected∙→is-connected {X = _ , y′ , Fy′≅y} λ (x , Fx≅y) → do
21 | (x≅y′ , eq) ← full≅ (Fy′≅y Iso⁻¹ ∘Iso Fx≅y)
22 | pure (Σ-pathp (ccat .to-path x≅y′)
23 | (≅-pathp _ _ (transport (λ i → PathP (λ j → Hom (F-map-path F ccat dcat x≅y′ (~ i) j) y) (Fx≅y .to) (Fy′≅y .to))
24 | (Hom-pathp-refll-iso (sym (ap from (Iso-swapl (sym eq))))))))
25 | where open Univalent dcat
26 |
--------------------------------------------------------------------------------
/src-1lab/Mystery.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Classical
2 | open import 1Lab.Prelude
3 |
4 | open import Data.Dec
5 |
6 | -- A weird constructive principle equivalent to Markov's principle + WLEM + ¬¬-shift
7 | -- https://types.pl/@ncf/112854858302377592
8 | -- https://x.com/ncfavier/status/1817846740944314834
9 | module Mystery where
10 |
11 | TNE : ∀ {ℓ} {P : Type ℓ} → ¬ ¬ ¬ P → ¬ P
12 | TNE h p = h λ k → k p
13 |
14 | case01 : ∀ {ℓ} {A : Type ℓ} → A → A → Nat → A
15 | case01 z s zero = z
16 | case01 z s (suc n) = s
17 |
18 | mystery MP DNS : Type
19 |
20 | mystery = (P : Nat → Ω) → (¬ ∀ n → ∣ P n ∣) → ∃ _ λ n → ¬ ∣ P n ∣
21 |
22 | MP = (P : Nat → Ω) → (∀ n → Dec ∣ P n ∣) → (¬ ∀ n → ∣ P n ∣) → ∃ _ λ n → ¬ ∣ P n ∣
23 |
24 | DNS = (P : Nat → Ω) → (∀ n → ¬ ¬ ∣ P n ∣) → ¬ ¬ ∀ n → ∣ P n ∣
25 |
26 | mystery→MP : mystery → MP
27 | mystery→MP m P _ = m P
28 |
29 | mystery→WLEM : mystery → WLEM
30 | mystery→WLEM m P = case m (case01 P (¬Ω P)) (λ h → h 1 (h 0)) of λ where
31 | zero p → yes p
32 | (suc _) p → no p
33 |
34 | mystery→DNS : mystery → DNS
35 | mystery→DNS m P h k = case m P k of h
36 |
37 | MP+WLEM+DNS→mystery : MP × WLEM × DNS → mystery
38 | MP+WLEM+DNS→mystery (mp , wlem , dns) P h =
39 | mp (λ n → ¬Ω ¬Ω P n) (λ n → wlem (¬Ω P n)) (λ k → dns P k h)
40 | <&> Σ-map id TNE
41 |
42 | mystery≃MP+WLEM+DNS : mystery ≃ (MP × WLEM × DNS)
43 | mystery≃MP+WLEM+DNS = prop-ext!
44 | ⟨ mystery→MP , ⟨ mystery→WLEM , mystery→DNS ⟩ ⟩
45 | MP+WLEM+DNS→mystery
46 |
--------------------------------------------------------------------------------
/src-1lab/Möbius.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 |
3 | open import Data.Int renaming (Int to ℤ)
4 |
5 | open import Homotopy.Space.Circle hiding (Cover ; decode)
6 |
7 | -- https://math.stackexchange.com/questions/4940313/giving-calculating-explicit-homomorphism-between-fundamental-groups
8 | module Möbius where
9 |
10 | data Möbius : Type where
11 | up down : Möbius
12 | seam : up ≡ down
13 | top : up ≡ down
14 | bottom : down ≡ up
15 | surf : PathP (λ i → top i ≡ bottom i) seam (sym seam)
16 |
17 | Cover : Möbius → Type
18 | Cover up = ℤ
19 | Cover down = ℤ
20 | Cover (seam i) = ℤ
21 | Cover (top i) = ua suc-equiv i
22 | Cover (bottom i) = ua suc-equiv i
23 | Cover (surf i j) = ua suc-equiv i
24 |
25 | decode : ∀ {x} → up ≡ x → Cover x
26 | decode p = subst Cover p 0
27 |
28 | ι : S¹ → Möbius
29 | ι = S¹-rec up (top ∙ bottom)
30 |
31 | ι* : ℤ → ℤ
32 | ι* = decode ∘ ap ι ∘ loopⁿ
33 |
34 | _ : ι* 1 ≡ 2
35 | _ = refl
36 |
--------------------------------------------------------------------------------
/src-1lab/ObjectClassifier.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Type
2 | open import 1Lab.Type.Sigma
3 | open import 1Lab.Type.Pointed
4 | open import 1Lab.Path
5 | open import 1Lab.HLevel
6 | open import 1Lab.HLevel.Closure
7 | open import 1Lab.Equiv
8 |
9 | -- Univalence from object classifiers in the sense of higher topos theory.
10 | module ObjectClassifier where
11 |
12 | -- The type of arrows/bundles/fibrations.
13 | Bundle : ∀ ℓ → Type (lsuc ℓ)
14 | Bundle ℓ
15 | = Σ (Type ℓ) λ A
16 | → Σ (Type ℓ) λ B
17 | → A → B
18 |
19 | -- The standard pullback construction (HoTT book 2.15.11).
20 | record Pullback {ℓ ℓ'} {B : Type ℓ} {C D : Type ℓ'} (s : B → D) (q : C → D) : Type (ℓ ⊔ ℓ') where
21 | constructor pb
22 | field
23 | pb₁ : B
24 | pb₂ : C
25 | pbeq : s pb₁ ≡ q pb₂
26 |
27 | open Pullback
28 |
29 | pb-path : ∀ {ℓ ℓ'} {B : Type ℓ} {C D : Type ℓ'} {s : B → D} {q : C → D} → {a b : Pullback s q}
30 | → (p1 : a .pb₁ ≡ b .pb₁) → (p2 : a .pb₂ ≡ b .pb₂) → PathP (λ i → s (p1 i) ≡ q (p2 i)) (a .pbeq) (b .pbeq)
31 | → a ≡ b
32 | pb-path p1 p2 pe i = pb (p1 i) (p2 i) (pe i)
33 |
34 | -- The morphisms of interest between bundles p : A → B and q : C → D are pairs
35 | -- r : A → C, s : B → D that make a *pullback square*:
36 | -- r
37 | -- A ------> C
38 | -- | ⯾ |
39 | -- p | | q
40 | -- v v
41 | -- B ------> D
42 | -- s
43 | -- Rather than laboriously state the universal property of a pullback, we take it
44 | -- on faith that the construction above has the universal property (this is
45 | -- exercise 2.11 in the HoTT book) and simply define "being a pullback" as having
46 | -- r and p factor through an equivalence A ≃ Pullback s q.
47 | -- This completely determines r by the factorisation r = pb₂ ∘ e .fst, so we can
48 | -- omit it by contractibility of singletons.
49 | _⇒_ : ∀ {ℓ} {ℓ'} → Bundle ℓ → Bundle ℓ' → Type (ℓ ⊔ ℓ')
50 | (A , B , p) ⇒ (C , D , q)
51 | = Σ (B → D) λ s
52 | → Σ (A ≃ Pullback s q) λ e
53 | → p ≡ pb₁ ∘ e .fst
54 |
55 | -- An object classifier is a *universal* bundle U∙ → U such that any other
56 | -- bundle has a unique map (i.e. pullback square) into it.
57 | -- Categorically, it is a terminal object in the category of arrows and pullback squares.
58 | is-classifier : ∀ {ℓ} → Bundle (lsuc ℓ) → Type (lsuc ℓ)
59 | is-classifier {ℓ} u = ∀ (p : Bundle ℓ) → is-contr (p ⇒ u)
60 |
61 | -- The projection from the type of pointed types to the type of types is our
62 | -- universal bundle: the fibre above A : Type ℓ is equivalent to A itself.
63 | Type↓ : ∀ ℓ → Bundle (lsuc ℓ)
64 | Type↓ ℓ = Type∙ ℓ , Type ℓ , fst
65 |
66 | Type↓-fibre : ∀ {ℓ} (A : Type ℓ) → A ≃ Pullback {B = Lift ℓ ⊤} {C = Type∙ ℓ} (λ _ → A) fst
67 | Type↓-fibre A = Iso→Equiv λ where
68 | .fst a → pb _ (A , a) refl
69 | .snd .is-iso.from (pb _ (A' , a) eq) → transport (sym eq) a
70 | .snd .is-iso.linv → transport-refl
71 | .snd .is-iso.rinv (pb _ (A' , a) eq) → pb-path refl (sym (Σ-path (sym eq) refl)) λ i j → eq (i ∧ j)
72 |
73 | postulate
74 | -- We assume that Type↓ is an object classifier in the sense above, and show that
75 | -- this makes it a univalent universe.
76 | Type↓-is-classifier : ∀ {ℓ} → is-classifier (Type↓ ℓ)
77 |
78 | -- Every type is trivially a bundle over the unit type.
79 | ! : ∀ {ℓ} → Type ℓ → Bundle ℓ
80 | ! A = A , Lift _ ⊤ , _
81 |
82 | -- The key observation is that the type of pullback squares from ! A to Type↓ is
83 | -- equivalent to the type of types equipped with an equivalence to A.
84 | -- Since the former was assumed to be contractible, so is the latter.
85 | lemma : ∀ {ℓ} (A : Type ℓ) → (! A ⇒ Type↓ ℓ) ≃ Σ (Type ℓ) (λ B → A ≃ B)
86 | lemma {ℓ} A = Iso→Equiv λ where
87 | .fst (ty , e , _) → ty _ , e ∙e Type↓-fibre (ty _) e⁻¹
88 | .snd .is-iso.from (B , e) → (λ _ → B) , e ∙e Type↓-fibre B , refl
89 | .snd .is-iso.linv (ty , e , _) → Σ-pathp refl (Σ-pathp (Σ-prop-path is-equiv-is-prop
90 | (funext λ _ → Equiv.ε (Type↓-fibre (ty _)) _)) refl)
91 | .snd .is-iso.rinv (B , e) → Σ-pathp refl (Σ-prop-path is-equiv-is-prop
92 | (funext λ _ → Equiv.η (Type↓-fibre B) _))
93 |
94 | -- Equivalences form an identity system, which is another way to state univalence.
95 | univalence : ∀ {ℓ} (A : Type ℓ) → is-contr (Σ (Type ℓ) λ B → A ≃ B)
96 | univalence {ℓ} A = Equiv→is-hlevel 0 (lemma A e⁻¹) (Type↓-is-classifier (! A))
97 |
--------------------------------------------------------------------------------
/src-1lab/PointwiseMonoidal.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Prelude
2 | open import Cat.Functor.Base
3 | open import Cat.Functor.Compose
4 | open import Cat.Functor.Constant
5 | open import Cat.Functor.Equivalence.Path
6 | open import Cat.Monoidal.Base
7 | open import Cat.Monoidal.Diagram.Monoid
8 | open import Cat.Instances.Product
9 | open import Cat.Displayed.Base
10 | open import Cat.Displayed.Total
11 |
12 | open Monoidal-category
13 | open Precategory
14 | open Functor
15 | open _=>_
16 |
17 | -- ⚠️ WIP ⚠️
18 | module PointwiseMonoidal
19 | {o o′ ℓ ℓ′} (C : Precategory o ℓ) (D : Precategory o′ ℓ′)
20 | (M : Monoidal-category D)
21 | where
22 |
23 | Pointwise : Monoidal-category Cat[ C , D ]
24 | Pointwise = pw where
25 | prod : Functor (Cat[ C , D ] ×ᶜ Cat[ C , D ]) Cat[ C , D ]
26 | prod .F₀ (a , b) = M .-⊗- F∘ Cat⟨ a , b ⟩
27 | prod .F₁ {x = x} {y = y} (na , nb) = M .-⊗- ▸ nat where
28 | nat : Cat⟨ x .fst , x .snd ⟩ => Cat⟨ y .fst , y .snd ⟩
29 | nat .η x = (na .η x) , (nb .η x)
30 | nat .is-natural x y f i = (na .is-natural x y f i) , (nb .is-natural x y f i)
31 | prod .F-id = ext λ _ → M .-⊗- .F-id
32 | prod .F-∘ f g = ext λ _ → M .-⊗- .F-∘ _ _
33 | pw : Monoidal-category Cat[ C , D ]
34 | pw .-⊗- = prod
35 | pw .Unit = Const (M .Unit)
36 | pw .unitor-l = {! M .unitor-l !}
37 | pw .unitor-r = {! !}
38 | pw .associator = {! !}
39 | pw .triangle = {! !}
40 | pw .pentagon = {! !}
41 |
42 | MonCD→CMonD : Functor (∫ Mon[ Pointwise ]) (Cat[ C , ∫ Mon[ M ] ])
43 | MonCD→CMonD .F₀ (F , mon) .F₀ c = F .F₀ c , {! !}
44 | MonCD→CMonD .F₀ (F , mon) .F₁ = {! !}
45 | MonCD→CMonD .F₀ (F , mon) .F-id = {! !}
46 | MonCD→CMonD .F₀ (F , mon) .F-∘ = {! !}
47 | MonCD→CMonD .F₁ = {! !}
48 | MonCD→CMonD .F-id = {! !}
49 | MonCD→CMonD .F-∘ = {! !}
50 |
51 | MonCD≡CMonD : ∫ Mon[ Pointwise ] ≡ Cat[ C , ∫ Mon[ M ] ]
52 | MonCD≡CMonD = Precategory-path MonCD→CMonD {! !}
53 |
--------------------------------------------------------------------------------
/src-1lab/PostcomposeNotFull.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Instances.Shape.Involution
2 | open import Cat.Instances.Shape.Interval
3 | open import Cat.Functor.Properties
4 | open import Cat.Functor.Compose
5 | open import Cat.Prelude
6 |
7 | open import Data.Bool
8 |
9 | open Precategory
10 | open Functor
11 | open _=>_
12 |
13 | module PostcomposeNotFull where
14 |
15 | {-
16 | We prove that it is NOT the case that, for every full functor p, the
17 | postcomposition functor p ∘ — is full.
18 | -}
19 |
20 | claim =
21 | ∀ {o ℓ o' ℓ' od ℓd} {C : Precategory o ℓ} {C' : Precategory o' ℓ'} {D : Precategory od ℓd}
22 | → (p : Functor C C') → is-full p → is-full (postcompose p {D = D})
23 |
24 | module _ (assume : claim) where
25 | {-
26 | The counterexample consists of the following category (identities omitted):
27 | https://q.uiver.app/#q=WzAsMixbMCwwLCJhIl0sWzAsMSwiYiJdLFswLDBdLFsxLDEsIiIsMix7InJhZGl1cyI6LTN9XSxbMCwxLCIiLDAseyJjdXJ2ZSI6LTF9XSxbMCwxLCIiLDEseyJjdXJ2ZSI6MX1dXQ==
28 | where the loops on a and b are involutions, the involution on a swaps
29 | the two morphisms a ⇉ b, and the involution on b leaves them alone.
30 | There is a full functor p from C to the walking arrow that collapses
31 | all the morphisms, and there are two inclusion functors F and G from
32 | the walking involution into C. A natural transformation p ∘ F ⇒ p ∘ G
33 | is trivial, but a natural transformation F ⇒ G is a "ℤ/2ℤ-equivariant"
34 | morphism a → b, that is one that commutes with the involutions on a and b.
35 | There is no such thing in C, hence the action of p ∘ — on natural
36 | transformations (whiskering) cannot be surjective.
37 | -}
38 |
39 | C : Precategory lzero lzero
40 | C .Ob = Bool
41 | C .Hom true true = Bool
42 | C .Hom true false = Bool
43 | C .Hom false true = ⊥
44 | C .Hom false false = Bool
45 | C .Hom-set true true = hlevel 2
46 | C .Hom-set true false = hlevel 2
47 | C .Hom-set false true = hlevel 2
48 | C .Hom-set false false = hlevel 2
49 | C .id {true} = false
50 | C .id {false} = false
51 | C ._∘_ {true} {true} {true} = xor
52 | C ._∘_ {false} {false} {false} = xor
53 | C ._∘_ {true} {true} {false} f g = xor g f
54 | C ._∘_ {true} {false} {false} f g = g
55 | C .idr {true} {true} f = xor-falser f
56 | C .idr {true} {false} f = refl
57 | C .idr {false} {false} f = xor-falser f
58 | C .idl {true} {true} f = refl
59 | C .idl {true} {false} f = refl
60 | C .idl {false} {false} f = refl
61 | C .assoc {true} {true} {true} {true} f g h = xor-associative f g h
62 | C .assoc {false} {false} {false} {false} f g h = xor-associative f g h
63 | C .assoc {true} {true} {true} {false} f true true = sym (not-involutive f)
64 | C .assoc {true} {true} {true} {false} f true false = refl
65 | C .assoc {true} {true} {true} {false} f false h = refl
66 | C .assoc {true} {true} {false} {false} f g h = refl
67 | C .assoc {true} {false} {false} {false} f g h = refl
68 |
69 | p : Functor C (0≤1 ^op)
70 | p .F₀ o = o
71 | p .F₁ {true} {true} = _
72 | p .F₁ {true} {false} = _
73 | p .F₁ {false} {true} ()
74 | p .F₁ {false} {false} = _
75 | p .F-id {true} = refl
76 | p .F-id {false} = refl
77 | p .F-∘ {true} {true} {true} f g = refl
78 | p .F-∘ {true} {true} {false} f g = refl
79 | p .F-∘ {true} {false} {false} f g = refl
80 | p .F-∘ {false} {false} {false} f g = refl
81 |
82 | p-is-full : is-full p
83 | p-is-full {true} {true} _ = inc (false , refl)
84 | p-is-full {true} {false} _ = inc (false , refl)
85 | p-is-full {false} {false} _ = inc (false , refl)
86 |
87 | p*-is-full : is-full (postcompose p {D = ∙⤮∙})
88 | p*-is-full = assume p p-is-full
89 |
90 | F G : Functor ∙⤮∙ C
91 | F .F₀ _ = true
92 | F .F₁ f = f
93 | F .F-id = refl
94 | F .F-∘ _ _ = refl
95 | G .F₀ _ = false
96 | G .F₁ f = f
97 | G .F-id = refl
98 | G .F-∘ _ _ = refl
99 |
100 | impossible : F => G → ⊥
101 | impossible θ = not-no-fixed (sym (θ .is-natural _ _ true))
102 |
103 | pθ : p F∘ F => p F∘ G
104 | pθ .η = _
105 | pθ .is-natural _ _ _ = refl
106 |
107 | θ : ∥ F => G ∥
108 | θ = fst <$> p*-is-full pθ
109 |
110 | contradiction : ⊥
111 | contradiction = rec! impossible θ
112 |
--------------------------------------------------------------------------------
/src-1lab/PresheafExponential.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Prelude
2 | open import Cat.Functor.Base
3 | open import Cat.Functor.Naturality
4 | open import Cat.Instances.Presheaf.Limits
5 | open import Cat.Instances.Presheaf.Exponentials
6 | open import Cat.Diagram.Exponential
7 | open import Cat.Diagram.Product
8 | import Cat.Reasoning
9 |
10 | module PresheafExponential {ℓ} {C : Precategory ℓ ℓ} where
11 |
12 | module C = Cat.Reasoning C
13 | module PSh = Cat.Reasoning (PSh ℓ C)
14 | open Binary-products (PSh ℓ C) (PSh-products _ C)
15 | open Cartesian-closed (PSh-closed C)
16 |
17 | open Functor
18 | open _=>_
19 |
20 | module _ b a where
21 | open Exponential (has-exp a b)
22 | renaming (B^A to infixr 50 _^_)
23 | using () public
24 |
25 | module _ (K L M : PSh.Ob) where
26 |
27 | internal-currying : M ^ (K ⊗₀ L) PSh.≅ (M ^ K) ^ L
28 | internal-currying = PSh.make-iso
29 | (λ where
30 | .η n f .η q (v , y) .η p (u , x) → f .η p (v C.∘ u , x , L .F₁ u y)
31 | .η n f .η q (v , y) .is-natural → {! !}
32 | .η n f .is-natural → {! !}
33 | .is-natural → {! !})
34 | (λ where
35 | .η n g .η q (v , x , y) → g .η q (v , y) .η q (C.id , x)
36 | .η n g .is-natural → {! !}
37 | .is-natural → {! !})
38 | (ext λ n g q v y p u x →
39 | ⌜ g .η p (v C.∘ u , L .F₁ u y) ⌝ .η p (C.id , x) ≡⟨ g .is-natural _ _ u $ₚ (v , y) ηₚ p $ₚ (C.id , x) ⟩
40 | (M ^ K) .F₁ u (g .η q (v , y)) .η p (C.id , x) ≡⟨⟩
41 | g .η q (v , y) .η p (⌜ u C.∘ C.id ⌝ , x) ≡⟨ ap! (C.idr u) ⟩
42 | g .η q (v , y) .η p (u , x) ∎)
43 | {! !}
44 |
--------------------------------------------------------------------------------
/src-1lab/Probability.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 |
3 | open import Data.Dec
4 | open import Data.Fin
5 | open import Data.Fin.Closure
6 |
7 | module Probability where
8 |
9 | -- “I have two children, (at least) one of whom is a boy born on a Tuesday -
10 | -- what is the probability that both children are boys?”
11 |
12 | -- Simplifying assumptions: gender is binary; gender and day of birth are
13 | -- uniformly distributed.
14 | Gender = Fin 2
15 | Day = Fin 7
16 | Child = Fin 2
17 |
18 | Sample = Child → Day × Gender
19 |
20 | count : (A : Sample → Type) → ⦃ ∀ {s} → Finite (A s) ⦄ → Nat
21 | count A = cardinality {A = Σ Sample A}
22 |
23 | condition : Sample → Type
24 | condition s = ∃[ i ∈ Child ] s i ≡ (1 , 1)
25 |
26 | event : Sample → Type
27 | event s = (i : Child) → s i .snd ≡ 1
28 |
29 | answer : Nat × Nat -- formal fraction
30 | answer = count (λ s → event s × condition s) , count condition
31 |
32 | _ : answer ≡ (13 , 27)
33 | _ = refl
34 |
--------------------------------------------------------------------------------
/src-1lab/Skeletons.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Functor.Base
2 | open import Cat.Functor.Equivalence
3 | open import Cat.Functor.FullSubcategory
4 | open import Cat.Functor.Properties
5 | open import Cat.Instances.FinSets
6 | open import Cat.Instances.Sets
7 | open import Cat.Prelude
8 | open import Cat.Skeletal
9 | open import Data.Bool
10 | open import Data.Fin
11 | open import Data.Nat
12 |
13 | import Cat.Reasoning
14 |
15 | open Functor
16 | open is-precat-iso
17 |
18 | {-
19 | Formalising parts of https://math.stackexchange.com/a/4943344, with
20 | finite-dimensional real vector spaces replaced with finite sets
21 | (the situation is exactly the same).
22 | -}
23 | module Skeletons where
24 |
25 | module Sets {ℓ} = Cat.Reasoning (Sets ℓ)
26 |
27 | {-
28 | In the role of the skeletal category whose objects are natural numbers
29 | representing ℝⁿ and whose morphisms are matrices, we use the skeletal
30 | category whose objects are natural numbers representing the standard
31 | finite sets [n] and whose morphisms are functions.
32 | -}
33 | S : Precategory lzero lzero
34 | S = FinSets
35 |
36 | S-is-skeletal : is-skeletal S
37 | S-is-skeletal = FinSets-is-skeletal
38 |
39 | {-
40 | In the role of the univalent category of finite-dimensional real vector
41 | spaces, we use the univalent category of finite sets, here realised as
42 | the *essential image* of the inclusion of S into sets.
43 | Explicitly, an object of C is a set X such that there merely exists a
44 | natural number n such that X ≃ [n].
45 | Equivalently, an object of C is a set X equipped with a natural number
46 | n such that ∥ X ≃ [n] ∥ (we can extract n from the truncation because
47 | the statements X ≃ [n] are mutually exclusive for distinct n).
48 | C is a Rezk completion of S.
49 | -}
50 | C : Precategory (lsuc lzero) lzero
51 | C = Essential-image Fin→Sets
52 |
53 | C-is-category : is-category C
54 | C-is-category = Essential-image-is-category Fin→Sets Sets-is-category
55 |
56 | {-
57 | Finally, if we remove the truncation (but do not change the morphisms),
58 | we get a skeletal category *isomorphic* to S, because we can contract X
59 | away. This is entirely analogous to the way that the naïve definition
60 | of the image of a function using Σ instead of ∃ yields the domain of
61 | the function (https://1lab.dev/1Lab.Counterexamples.Sigma.html).
62 | -}
63 | C' : Precategory (lsuc lzero) lzero
64 | C' = Restrict {C = Sets _} λ X → Σ[ n ∈ Nat ] Fin→Sets .F₀ n Sets.≅ X
65 |
66 | S→C' : Functor S C'
67 | S→C' .F₀ n = el! (Fin n) , n , Sets.id-iso
68 | S→C' .F₁ f = f
69 | S→C' .F-id = refl
70 | S→C' .F-∘ _ _ = refl
71 |
72 | S≡C' : is-precat-iso S→C'
73 | S≡C' .has-is-ff = id-equiv
74 | S≡C' .has-is-iso = inverse-is-equiv (e .snd) where
75 | e : (Σ[ X ∈ Set lzero ] Σ[ n ∈ Nat ] Fin→Sets .F₀ n Sets.≅ X) ≃ Nat
76 | e = Σ-swap₂ ∙e Σ-contract λ n → is-contr-ΣR Sets-is-category
77 |
78 | {-
79 | Since C is a Rezk completion of S, we should expect to have a fully
80 | faithful and essentially surjective functor S → C.
81 | -}
82 |
83 | S→C : Functor S C
84 | S→C = Essential-inc Fin→Sets
85 |
86 | S→C-is-ff : is-fully-faithful S→C
87 | S→C-is-ff = ff→Essential-inc-ff Fin→Sets Fin→Sets-is-ff
88 |
89 | S→C-is-eso : is-eso S→C
90 | S→C-is-eso = Essential-inc-eso Fin→Sets
91 |
92 | {-
93 | However, this functor is *not* an equivalence of categories: in order
94 | to obtain a functor going the other way, we would have to choose an
95 | enumeration of every finite set in a coherent way. This is a form of
96 | global choice, which is just false in homotopy type theory
97 | (https://1lab.dev/1Lab.Counterexamples.GlobalChoice.html).
98 | -}
99 |
100 | module _ (S≃C : is-equivalence S→C) where private
101 | open is-equivalence S≃C renaming (F⁻¹ to C→S)
102 | module C = Cat.Reasoning C
103 |
104 | module _ (X : Set lzero) (e : ∥ ⌞ X ⌟ ≃ Fin 2 ∥) where
105 | c : C.Ob
106 | c = X , ((λ e → 2 , equiv→iso (e e⁻¹)) <$> e)
107 |
108 | chosen : ⌞ X ⌟
109 | chosen with C→S .F₀ c | counit.ε c | counit-iso c
110 | ... | suc n | ε | _ = ε 0
111 | ... | zero | ε | ε-inv = absurd (case e of λ e →
112 | zero≠suc (Fin-injective (iso→equiv (sub-iso→super-iso _ (C.invertible→iso ε ε-inv)) ∙e e)))
113 |
114 | b : Bool
115 | b = chosen (el! Bool) enumeration
116 |
117 | swap : Bool ≡ Bool
118 | swap = ua (not , not-is-equiv)
119 |
120 | p : PathP (λ i → swap i) b b
121 | p = ap₂ chosen (n-ua _) prop!
122 |
123 | ¬S≃C : ⊥
124 | ¬S≃C = not-no-fixed (from-pathp⁻ p)
125 |
--------------------------------------------------------------------------------
/src-1lab/SplitMonoSet.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Prelude
2 | import Cat.Reasoning
3 | open import 1Lab.Classical
4 | open import Data.Dec
5 | open import Data.Sum
6 |
7 | -- If every split monomorphism with inhabited domain splits in Sets then excluded middle holds.
8 | module SplitMonoSet where
9 |
10 | module Sets = Cat.Reasoning (Sets lzero)
11 |
12 | module _ (every-mono-splits : ∀ {A B} (a : ∥ ⌞ A ⌟ ∥) (f : Sets.Hom A B) (f-mono : Sets.is-monic {a = A} {B} f) → Sets.is-split-monic {a = A} {B} f) where
13 | lem : LEM
14 | lem P = ∥-∥-out! do
15 | Sets.make-retract f⁻¹ ret ← f-split
16 | pure (go (f⁻¹ (inr tt)) λ p → ret $ₚ inr p)
17 | where
18 | A : Set lzero
19 | A = el! (⊤ ⊎ ⌞ P ⌟)
20 | B : Set lzero
21 | B = el! (⊤ ⊎ ⊤)
22 | f : Sets.Hom A B
23 | f = ⊎-map _ _
24 | f-mono : Sets.is-monic {a = A} {B} f
25 | f-mono = embedding→monic {f = f} $ injective→is-embedding! λ where
26 | {inl _} {inl _} p → refl
27 | {inl _} {inr _} p → absurd (inl≠inr p)
28 | {inr _} {inl _} p → absurd (inr≠inl p)
29 | {inr _} {inr _} p → ap inr prop!
30 | f-split : Sets.is-split-monic {a = A} {B} f
31 | f-split = every-mono-splits (inc (inl _)) f λ {c} → f-mono {c}
32 | go : (f⁻¹r : ∣ A ∣) → (∀ p → f⁻¹r ≡ inr p) → Dec ∣ P ∣
33 | go (inl _) l = no λ p → inl≠inr (l p)
34 | go (inr p) l = yes p
35 |
--------------------------------------------------------------------------------
/src-1lab/SyntheticCategoricalDuality.lagda.md:
--------------------------------------------------------------------------------
1 | ```agda
2 | open import 1Lab.Reflection.Regularity
3 | open import 1Lab.Path.Cartesian
4 | open import 1Lab.Reflection hiding (absurd)
5 |
6 | open import Cat.Functor.Equivalence.Path
7 | open import Cat.Functor.Equivalence
8 | open import Cat.Prelude hiding (_[_↦_])
9 |
10 | open import Data.Fin
11 | ```
12 |
13 | A synthetic account of categorical duality, based on an idea by [**David Wärn**](https://dwarn.se/).
14 |
15 | The theory of categories has a fundamental S₂-symmetry that swaps "source"
16 | and "target", which can be expressed synthetically by defining categories
17 | in the context of the delooping BS₂.
18 | By choosing as our delooping the type of 2-element types, this amounts
19 | to defining categories relative to an arbitrary 2-element type X, which
20 | we can think of as the set {source, target} except we've forgotten
21 | which is which.
22 | Then, instantiating this with a chosen 2-element type recovers usual
23 | categories, and the non-trivial symmetry of BS₂ automatically gives
24 | a symmetry of the type of categories which coincides with the usual
25 | categorical opposite.
26 |
27 | ```agda
28 | module SyntheticCategoricalDuality where
29 | ```
30 |
31 | Some auxiliary definitions
32 |
33 | ```agda
34 | private variable
35 | ℓ o h : Level
36 | X O : Type ℓ
37 | H : O → Type ℓ
38 | a b c : O
39 | i j k : X
40 |
41 | excluded-middle : ∀ {x y z : Bool} → x ≠ y → y ≠ z → x ≡ z
42 | excluded-middle {true} {y} {true} x≠y y≠z = refl
43 | excluded-middle {true} {y} {false} x≠y y≠z = absurd (x≠y (sym (x≠false→x≡true y y≠z)))
44 | excluded-middle {false} {y} {true} x≠y y≠z = absurd (x≠y (sym (x≠true→x≡false y y≠z)))
45 | excluded-middle {false} {y} {false} x≠y y≠z = refl
46 |
47 | instance
48 | Extensional-Bool-map
49 | : ∀ {ℓ ℓr} {C : Bool → Type ℓ} → ⦃ e : ∀ {b} → Extensional (C b) ℓr ⦄
50 | → Extensional ((b : Bool) → C b) ℓr
51 | Extensional-Bool-map ⦃ e ⦄ .Pathᵉ f g =
52 | e .Pathᵉ (f false) (g false) × e .Pathᵉ (f true) (g true)
53 | Extensional-Bool-map ⦃ e ⦄ .reflᵉ f =
54 | e .reflᵉ (f false) , e .reflᵉ (f true)
55 | Extensional-Bool-map ⦃ e ⦄ .idsᵉ .to-path (false≡ , true≡) = funext λ where
56 | true → e .idsᵉ .to-path true≡
57 | false → e .idsᵉ .to-path false≡
58 | Extensional-Bool-map ⦃ e ⦄ .idsᵉ .to-path-over (false≡ , true≡) =
59 | Σ-pathp (e .idsᵉ .to-path-over false≡) (e .idsᵉ .to-path-over true≡)
60 |
61 | Extensional-Bool-homotopy
62 | : ∀ {ℓ ℓr} {C : Bool → Type ℓ} → ⦃ e : ∀ {b} {x y : C b} → Extensional (x ≡ y) ℓr ⦄
63 | → {f g : (b : Bool) → C b}
64 | → Extensional (f ≡ g) ℓr
65 | Extensional-Bool-homotopy ⦃ e ⦄ {f} {g} .Pathᵉ p q =
66 | e .Pathᵉ (p $ₚ false) (q $ₚ false) × e .Pathᵉ (p $ₚ true) (q $ₚ true)
67 | Extensional-Bool-homotopy ⦃ e ⦄ .reflᵉ p =
68 | e .reflᵉ (p $ₚ false) , e .reflᵉ (p $ₚ true)
69 | Extensional-Bool-homotopy ⦃ e ⦄ .idsᵉ .to-path (false≡ , true≡) = funext-square λ where
70 | true → e .idsᵉ .to-path true≡
71 | false → e .idsᵉ .to-path false≡
72 | Extensional-Bool-homotopy ⦃ e ⦄ .idsᵉ .to-path-over (false≡ , true≡) =
73 | Σ-pathp (e .idsᵉ .to-path-over false≡) (e .idsᵉ .to-path-over true≡)
74 |
75 | Bool-η : (b : Bool → O) → if (b true) (b false) ≡ b
76 | Bool-η b = ext (refl , refl)
77 | ```
78 |
79 |
80 | ```agda
81 | -- We define X-(pre)categories relative to a 2-element type X.
82 | module X (o h : Level) (X : Type) (e : ∥ X ≃ Bool ∥) where
83 | ```
84 |
85 | Some more auxiliary definitions
86 |
87 | ```agda
88 | private instance
89 | Finite-X : Finite X
90 | Finite-X = ⦇ Equiv→listing (e <&> _e⁻¹) auto ⦈
91 |
92 | Discrete-X : Discrete X
93 | Discrete-X = Finite→Discrete
94 |
95 | H-Level-X : H-Level X 2
96 | H-Level-X = Finite→H-Level
97 |
98 | _[_↦_] : (X → O) → X → O → X → O
99 | _[_↦_] b x m i = ifᵈ i ≡? x then m else b i
100 |
101 | assign-id : (b : X → O) → (x : X) → b [ x ↦ b x ] ≡ b
102 | assign-id b x = ext go where
103 | go : ∀ i → (b [ x ↦ b x ]) i ≡ b i
104 | go i with i ≡? x
105 | ... | yes p = ap b (sym p)
106 | ... | no _ = refl
107 |
108 | assign-const : (b : X → O) (i j : X) → j ≠ i → b [ j ↦ b i ] ≡ λ _ → b i
109 | assign-const b i j j≠i = ext go where
110 | go : ∀ k → (b [ j ↦ b i ]) k ≡ b i
111 | go k with k ≡? j
112 | ... | yes _ = refl
113 | ... | no k≠j = ap b $ ∥-∥-out! do
114 | e ← e
115 | pure (subst (λ X → {x y z : X} → x ≠ y → y ≠ z → x ≡ z)
116 | (ua (e e⁻¹)) excluded-middle k≠j j≠i)
117 |
118 | degenerate
119 | : (H : (X → O) → Type h) (b : X → O) (x : X) (f : H b) (id : H (λ _ → b x)) (i : X)
120 | → H (b [ i ↦ b x ])
121 | -- degenerate H b x f id i with i ≡ᵢ? x
122 | -- ... | yes reflᵢ = subst H (sym (assign-id b x)) f
123 | -- ... | no i≠x = subst H (sym (assign-const b x i (i≠x ⊙ Id≃path.from))) id
124 | -- NOTE performing the with-translation manually somehow results in fewer transports when X = Bool and x = i.
125 | -- I'm not sure what's happening here...
126 | degenerate H b x f id i = go (i ≡ᵢ? x) where
127 | go : Dec (i ≡ᵢ x) → H (b [ i ↦ b x ])
128 | go (yes reflᵢ) = subst H (sym (assign-id b x)) f
129 | go (no i≠x) = subst H (sym (assign-const b x i (i≠x ⊙ Id≃path.from))) id
130 | ```
131 |
132 |
133 | ```agda
134 | record XPrecategory : Type (lsuc (o ⊔ h)) where
135 | no-eta-equality
136 |
137 | field
138 | Ob : Type o
139 |
140 | -- Hom is a family indexed over "X-pairs" of objects, or boundaries.
141 | Hom : (X → Ob) → Type h
142 | Hom-set : (b : X → Ob) → is-set (Hom b)
143 |
144 | -- The identity lives over the constant pair.
145 | id : ∀ {x} → Hom λ _ → x
146 |
147 | -- Composition takes an outer boundary b, a middle object and an
148 | -- X-pair of morphisms with the appropriate boundaries and returns
149 | -- a morphism with boundary b.
150 | compose : (b : X → Ob) (m : Ob) → ((x : X) → Hom (b [ x ↦ m ])) → Hom b
151 |
152 | -- We can (and must) state both unit laws at once: given a "direction" x : X
153 | -- and a morphism f with boundary b, we can form the X-pair {f, id}
154 | -- where id lies in the direction x from f, and ask that the
155 | -- composite equal f.
156 | compose-id
157 | : (b : X → Ob) (f : Hom b) (x : X)
158 | → compose b (b x) (degenerate Hom b x f id) ≡ f
159 |
160 | -- TODO: associativity
161 | -- assoc
162 | -- : (b : X → Ob) (m n : Ob) (x : X)
163 | -- → compose b m (λ i → {! !}) ≡ compose b n {! !}
164 | ```
165 |
166 | Some lemmas about paths between X-precategories
167 |
168 | ```agda
169 | private
170 | hom-set : ∀ (C : XPrecategory) {b} → is-set (C .XPrecategory.Hom b)
171 | hom-set C = C .XPrecategory.Hom-set _
172 |
173 | instance
174 | hlevel-proj-xhom : hlevel-projection (quote XPrecategory.Hom)
175 | hlevel-proj-xhom .hlevel-projection.has-level = quote hom-set
176 | hlevel-proj-xhom .hlevel-projection.get-level _ = pure (lit (nat 2))
177 | hlevel-proj-xhom .hlevel-projection.get-argument (c v∷ _) = pure c
178 | hlevel-proj-xhom .hlevel-projection.get-argument _ = typeError []
179 |
180 | private unquoteDecl record-iso = declare-record-iso record-iso (quote XPrecategory)
181 |
182 | XPrecategory-path
183 | : ∀ {C D : XPrecategory} (let module C = XPrecategory C; module D = XPrecategory D)
184 | → (ob≡ : C.Ob ≡ D.Ob)
185 | → (hom≡ : PathP (λ i → (X → ob≡ i) → Type h) C.Hom D.Hom)
186 | → (id≡ : PathP (λ i → ∀ {x} → hom≡ i (λ _ → x)) C.id D.id)
187 | → (compose≡ : PathP (λ i → ∀ (b : X → ob≡ i) (m : ob≡ i) (f : ∀ x → hom≡ i (b [ x ↦ m ])) → hom≡ i b) C.compose D.compose)
188 | → C ≡ D
189 | XPrecategory-path ob≡ hom≡ id≡ compose≡ = Iso.injective record-iso
190 | $ Σ-pathp ob≡ $ Σ-pathp hom≡ $ Σ-pathp prop!
191 | $ Σ-pathp id≡ $ Σ-pathp compose≡ $ hlevel 0 .centre
192 | ```
193 |
194 |
195 | ```agda
196 | open X using (XPrecategory; XPrecategory-path)
197 |
198 | -- We recover categories by choosing a 2-element type X with designated
199 | -- source and target elements. Here we pick the booleans with
200 | -- the convention that true = source and false = target.
201 | 2Precategory : (o h : Level) → Type (lsuc (o ⊔ h))
202 | 2Precategory o h = XPrecategory o h Bool (inc id≃)
203 |
204 | module _ {o h : Level} where
205 | module B = X o h Bool (inc id≃)
206 |
207 | Precategory→2Precategory : Precategory o h → 2Precategory o h
208 | Precategory→2Precategory C = C' where
209 | module C = Precategory C
210 | open XPrecategory
211 | C' : 2Precategory o h
212 | C' .Ob = C.Ob
213 | C' .Hom b = C.Hom (b true) (b false)
214 | C' .Hom-set b = C.Hom-set _ _
215 | C' .id = C.id
216 | C' .compose b m f = f true C.∘ f false
217 | C' .compose-id b f true = ap₂ C._∘_ (transport-refl f) (transport-refl C.id) ∙ C.idr f
218 | C' .compose-id b f false = ap₂ C._∘_ (transport-refl C.id) (transport-refl f) ∙ C.idl f
219 | -- C' .assoc = ?
220 |
221 | 2Precategory→Precategory : 2Precategory o h → Precategory o h
222 | 2Precategory→Precategory C' = C where
223 | module C' = XPrecategory C'
224 | open Precategory
225 | C : Precategory o h
226 | C .Ob = C'.Ob
227 | C .Hom a b = C'.Hom (if a b)
228 | C .Hom-set a b = C'.Hom-set _
229 | C .id = subst C'.Hom (ext (refl , refl)) C'.id
230 | C ._∘_ {a} {b} {c} f g = C'.compose (if a c) b λ where
231 | true → subst C'.Hom (ext (refl , refl)) f
232 | false → subst C'.Hom (ext (refl , refl)) g
233 | C .idr {x} {y} f =
234 | ap (C'.compose (if x y) x) (ext
235 | ( sym (subst-∙ C'.Hom _ _ C'.id)
236 | ∙ ap (λ p → subst C'.Hom p C'.id) (ext (∙-idr refl , ∙-idr refl))
237 | , ap (λ p → subst C'.Hom p f) (ext (refl , refl))))
238 | ∙ C'.compose-id (if x y) f true
239 | C .idl {x} {y} f =
240 | ap (C'.compose (if x y) y) (ext
241 | ( ap (λ p → subst C'.Hom p f) (ext (refl , refl))
242 | , sym (subst-∙ C'.Hom _ _ C'.id)
243 | ∙ ap (λ p → subst C'.Hom p C'.id) (ext (∙-idr refl , ∙-idr refl))))
244 | ∙ C'.compose-id (if x y) f false
245 | C .assoc = {! !}
246 |
247 | Precategory→2Precategory-is-iso : is-iso Precategory→2Precategory
248 | Precategory→2Precategory-is-iso .is-iso.from = 2Precategory→Precategory
249 | Precategory→2Precategory-is-iso .is-iso.rinv C' = XPrecategory-path _ _ _ _
250 | refl
251 | (ext λ b → ap C'.Hom (Bool-η b))
252 | (funextP' λ {a} → to-pathp⁻ (ap (λ p → subst C'.Hom p C'.id) (ext (refl , refl))))
253 | (funextP λ b → funextP λ m → funext-dep-i1 λ f →
254 | let
255 | path : PathP (λ i → C'.Hom (Bool-η b i))
256 | (C'.compose (if (b true) (b false)) m λ x → coe1→0 (λ i → C'.Hom (Bool-η b i B.[ x ↦ m ])) (f x))
257 | (C'.compose b m f)
258 | path i = C'.compose (Bool-η b i) m
259 | λ x → coe1→i (λ i → C'.Hom (Bool-η b i B.[ x ↦ m ])) i (f x)
260 | in
261 | ap (C'.compose (if (b true) (b false)) m) (ext
262 | ( sym (subst-∙ C'.Hom _ _ (f false))
263 | ∙ ap (λ p → subst C'.Hom p (f false)) (ext (∙-idr refl , ∙-idr refl))
264 | , sym (subst-∙ C'.Hom _ _ (f true))
265 | ∙ ap (λ p → subst C'.Hom p (f true)) (ext (∙-idr refl , ∙-idr refl))))
266 | ◁ path)
267 | where module C' = XPrecategory C'
268 | Precategory→2Precategory-is-iso .is-iso.linv C = Precategory-path F (iso id-equiv id-equiv)
269 | where
270 | module C = Precategory C
271 | open Functor
272 | F : Functor (2Precategory→Precategory (Precategory→2Precategory C)) C
273 | F .F₀ o = o
274 | F .F₁ f = f
275 | F .F-id = transport-refl C.id
276 | F .F-∘ f g = ap₂ C._∘_ (transport-refl f) (transport-refl g)
277 |
278 | Precategory≃2Precategory : Precategory o h ≃ 2Precategory o h
279 | Precategory≃2Precategory = Iso→Equiv (Precategory→2Precategory , Precategory→2Precategory-is-iso)
280 |
281 | -- We get categorical duality from the action of the X-category construction
282 | -- on the non-trivial path Bool ≡ Bool, and we check that this agrees
283 | -- with the usual categorical duality.
284 | duality : 2Precategory o h ≡ 2Precategory o h
285 | duality = ap₂ (XPrecategory _ _) (ua not≃) prop!
286 |
287 | _^Xop : 2Precategory o h → 2Precategory o h
288 | _^Xop = transport duality
289 |
290 | dualities-agree
291 | : (C : Precategory o h)
292 | → Precategory→2Precategory C ^Xop ≡ Precategory→2Precategory (C ^op)
293 | dualities-agree C = XPrecategory-path _ _ _ _
294 | refl
295 | (ext λ b → ap₂ C.Hom (transport-refl _) (transport-refl _))
296 | Regularity.reduce!
297 | (to-pathp (ext λ b m f → Regularity.reduce!))
298 | where module C = Precategory C
299 | ```
300 |
--------------------------------------------------------------------------------
/src-1lab/TangentBundlesOfSpheres.lagda.md:
--------------------------------------------------------------------------------
1 | ```agda
2 | open import 1Lab.Path.Cartesian
3 | open import 1Lab.Path.Reasoning
4 | open import 1Lab.Prelude
5 |
6 | open import Algebra.Group.Concrete.Abelian
7 | open import Algebra.Group.Concrete
8 |
9 | open import Data.Set.Truncation
10 | open import Data.Bool
11 | open import Data.Int
12 | open import Data.Nat
13 | open import Data.Sum
14 |
15 | open import Homotopy.Space.Suspension.Properties
16 | open import Homotopy.Connectedness.Automation
17 | open import Homotopy.Space.Suspension
18 | open import Homotopy.Connectedness
19 | open import Homotopy.Space.Circle
20 | open import Homotopy.Space.Sphere
21 | open import Homotopy.Base
22 |
23 | open import Meta.Idiom
24 | ```
25 |
26 | A formalisation of the first part of [The tangent bundles of spheres](https://www.youtube.com/watch?v=9T9B9XBjVpk)
27 | by David Jaz Myers, Ulrik Buchholtz, Dan Christensen and Egbert Rijke, up until
28 | the proof of the hairy ball theorem (except I don't have enough homotopy theory
29 | to conclude that n-1 must be odd from `flipΣⁿ ≡ id`).
30 |
31 | ```agda
32 | module TangentBundlesOfSpheres where
33 |
34 | record Functorial (M : Effect) : Typeω where
35 | private module M = Effect M
36 | field
37 | ⦃ Map-Functorial ⦄ : Map M
38 | map-id : ∀ {ℓ} {A : Type ℓ} → map {M} {A = A} id ≡ id
39 | map-∘
40 | : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
41 | → {f : B → C} {g : A → B}
42 | → map {M} (f ∘ g) ≡ map f ∘ map g
43 |
44 | map-iso : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
45 | → (e : A ≃ B) → is-iso (map (Equiv.to e))
46 | map-iso e .is-iso.from = map (Equiv.from e)
47 | map-iso e .is-iso.rinv mb =
48 | map (Equiv.to e) (map (Equiv.from e) mb) ≡˘⟨ map-∘ $ₚ mb ⟩
49 | map ⌜ Equiv.to e ∘ Equiv.from e ⌝ mb ≡⟨ ap! (funext (Equiv.ε e)) ⟩
50 | map id mb ≡⟨ map-id $ₚ mb ⟩
51 | mb ∎
52 | map-iso e .is-iso.linv ma =
53 | map (Equiv.from e) (map (Equiv.to e) ma) ≡˘⟨ map-∘ $ₚ ma ⟩
54 | map ⌜ Equiv.from e ∘ Equiv.to e ⌝ ma ≡⟨ ap! (funext (Equiv.η e)) ⟩
55 | map id ma ≡⟨ map-id $ₚ ma ⟩
56 | ma ∎
57 |
58 | map≃
59 | : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
60 | → (e : A ≃ B) → M.₀ A ≃ M.₀ B
61 | map≃ e = _ , is-iso→is-equiv (map-iso e)
62 |
63 | map-transport
64 | : ∀ {ℓ} {A : Type ℓ} {B : Type ℓ}
65 | → (p : A ≡ B) → map (transport p) ≡ transport (ap M.₀ p)
66 | map-transport {A = A} p i = comp (λ i → M.₀ A → M.₀ (p i)) (∂ i) λ where
67 | j (j = i0) → map-id i
68 | j (i = i0) → map (funextP (transport-filler p) j)
69 | j (i = i1) → funextP (transport-filler (ap M.₀ p)) j
70 |
71 | open Functorial ⦃ ... ⦄
72 |
73 | is-natural
74 | : ∀ {M N : Effect} (let module M = Effect M; module N = Effect N) ⦃ _ : Map M ⦄ ⦃ _ : Map N ⦄
75 | → (f : ∀ {ℓ} {A : Type ℓ} → M.₀ A → N.₀ A) → Typeω
76 | is-natural f =
77 | ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} {g : A → B}
78 | → ∀ a → map g (f a) ≡ f (map g a)
79 |
80 | -- Operations on suspensions: functorial action, flipping
81 |
82 | instance
83 | Map-Susp : Map (eff Susp)
84 | Map-Susp .Map.map f N = N
85 | Map-Susp .Map.map f S = S
86 | Map-Susp .Map.map f (merid a i) = merid (f a) i
87 |
88 | Functorial-Susp : Functorial (eff Susp)
89 | Functorial-Susp .Functorial.Map-Functorial = Map-Susp
90 | Functorial-Susp .Functorial.map-id = funext $ Susp-elim _ refl refl λ _ _ → refl
91 | Functorial-Susp .Functorial.map-∘ = funext $ Susp-elim _ refl refl λ _ _ → refl
92 |
93 | flipΣ : ∀ {ℓ} {A : Type ℓ} → Susp A → Susp A
94 | flipΣ N = S
95 | flipΣ S = N
96 | flipΣ (merid a i) = merid a (~ i)
97 |
98 | flipΣ∙ : ∀ {n} → Sⁿ (suc n) →∙ Sⁿ (suc n)
99 | flipΣ∙ = flipΣ , sym (merid N)
100 |
101 | flipΣ-involutive : ∀ {ℓ} {A : Type ℓ} → (p : Susp A) → flipΣ (flipΣ p) ≡ p
102 | flipΣ-involutive = Susp-elim _ refl refl λ _ _ → refl
103 |
104 | flipΣ≃ : ∀ {ℓ} {A : Type ℓ} → Susp A ≃ Susp A
105 | flipΣ≃ = flipΣ , is-involutive→is-equiv flipΣ-involutive
106 |
107 | flipΣ-natural : is-natural flipΣ
108 | flipΣ-natural = Susp-elim _ refl refl λ _ _ → refl
109 |
110 | twist : ∀ {ℓ} {A : Type ℓ} {a b : A} {p q : a ≡ b} (α : p ≡ q)
111 | → PathP (λ i → PathP (λ j → α i j ≡ α j (~ i))
112 | (λ k → p (~ i ∧ k))
113 | (λ k → q (~ i ∨ ~ k)))
114 | (λ j k → p (j ∨ k))
115 | (λ j k → q (j ∧ ~ k))
116 | twist α i j k = hcomp (∂ i ∨ ∂ j ∨ ∂ k) λ where
117 | l (l = i0) → α (I-interp k i j) (I-interp k j (~ i))
118 | l (i = i0) → α (~ l ∧ k ∧ j) (k ∨ j)
119 | l (i = i1) → α (l ∨ ~ k ∨ j) (~ k ∧ j)
120 | l (j = i0) → α (~ l ∧ ~ k ∧ i) (k ∧ ~ i)
121 | l (j = i1) → α (l ∨ k ∨ i) (~ k ∨ ~ i)
122 | l (k = i0) → α i j
123 | l (k = i1) → α j (~ i)
124 |
125 | -- Flipping ΣΣA along the first axis is homotopic to flipping along the second axis,
126 | -- by rotating 180°.
127 | rotateΣ : ∀ {ℓ} {A : Type ℓ} → map flipΣ ≡ flipΣ {A = Susp A}
128 | rotateΣ = funext $ Susp-elim _ (merid N) (sym (merid S)) (
129 | Susp-elim _ (flip₁ (double-connection _ _)) (double-connection _ _)
130 | λ a i j k → hcomp (∂ j ∨ ∂ k) λ where
131 | l (l = i0) → merid (merid a j) i
132 | l (j = i0) → merid N (I-interp l i k)
133 | l (j = i1) → merid S (I-interp l i (~ k))
134 | l (k = i0) → twist (λ i j → merid (merid a i) j) (~ i) j (~ l)
135 | l (k = i1) → twist (λ i j → merid (merid a i) j) j i l)
136 |
137 | Susp-ua→
138 | : ∀ {ℓ ℓ'} {A B : Type ℓ} {C : Type ℓ'}
139 | → {e : A ≃ B} {f : Susp A → C} {g : Susp B → C}
140 | → (∀ sa → f sa ≡ g (map (e .fst) sa))
141 | → PathP (λ i → Susp (ua e i) → C) f g
142 | Susp-ua→ h i N = h N i
143 | Susp-ua→ h i S = h S i
144 | Susp-ua→ {g = g} h i (merid a j) = hcomp (∂ i ∨ ∂ j) λ where
145 | k (k = i0) → g (merid (unglue a) j)
146 | k (i = i0) → h (merid a j) (~ k)
147 | k (i = i1) → g (merid a j)
148 | k (j = i0) → h N (i ∨ ~ k)
149 | k (j = i1) → h S (i ∨ ~ k)
150 |
151 | -- The tangent bundles of spheres
152 |
153 | Tⁿ⁻¹ : ∀ n → Sⁿ⁻¹ n → Type
154 | θⁿ⁻¹ : ∀ n → (p : Sⁿ⁻¹ n) → Susp (Tⁿ⁻¹ n p) ≃ Sⁿ⁻¹ n
155 |
156 | Tⁿ⁻¹ zero ()
157 | Tⁿ⁻¹ (suc n) = Susp-elim _
158 | (Sⁿ⁻¹ n)
159 | (Sⁿ⁻¹ n)
160 | λ p → ua (θⁿ⁻¹ n p e⁻¹ ∙e flipΣ≃ ∙e θⁿ⁻¹ n p)
161 |
162 | θⁿ⁻¹ zero ()
163 | θⁿ⁻¹ (suc n) = Susp-elim _
164 | id≃
165 | flipΣ≃
166 | λ p → Σ-prop-pathp! $ Susp-ua→ $ happly $ sym $
167 | let module θ = Equiv (θⁿ⁻¹ n p) in
168 | flipΣ ∘ map (θ.to ∘ flipΣ ∘ θ.from) ≡⟨ flipΣ ∘⟨ map-∘ ⟩
169 | flipΣ ∘ map θ.to ∘ map (flipΣ ∘ θ.from) ≡⟨ flipΣ ∘ map _ ∘⟨ map-∘ ⟩
170 | flipΣ ∘ map θ.to ∘ map flipΣ ∘ map θ.from ≡⟨ flipΣ ∘ map _ ∘⟨ rotateΣ ⟩∘ map _ ⟩
171 | flipΣ ∘ map θ.to ∘ flipΣ ∘ map θ.from ≡⟨ flipΣ ∘⟨ funext flipΣ-natural ⟩∘ map _ ⟩
172 | flipΣ ∘ flipΣ ∘ map θ.to ∘ map θ.from ≡⟨ funext flipΣ-involutive ⟩∘⟨refl ⟩
173 | map θ.to ∘ map θ.from ≡⟨ funext (is-iso.rinv (map-iso (θⁿ⁻¹ n p))) ⟩
174 | id ∎
175 |
176 | antipodeⁿ⁻¹ : ∀ n → Sⁿ⁻¹ n ≃ Sⁿ⁻¹ n
177 | antipodeⁿ⁻¹ zero = id≃
178 | antipodeⁿ⁻¹ (suc n) = map≃ (antipodeⁿ⁻¹ n) ∙e flipΣ≃
179 |
180 | θN : ∀ n → (p : Sⁿ⁻¹ n) → θⁿ⁻¹ n p .fst N ≡ p
181 | θN (suc n) = Susp-elim _ refl refl λ p → transpose $
182 | ap sym (∙-idl _ ∙ ∙-idl _ ∙ ∙-elimr (∙-idl _ ∙ ∙-idl _ ∙ ∙-idr _ ∙ ∙-idl _ ∙ ∙-idl _ ∙ ∙-idl _))
183 | ∙ ap merid (θN n p)
184 |
185 | θS : ∀ n → (p : Sⁿ⁻¹ n) → θⁿ⁻¹ n p .fst S ≡ Equiv.to (antipodeⁿ⁻¹ n) p
186 | θS (suc n) = Susp-elim _ refl refl λ p → transpose $
187 | ap sym (∙-idl _ ∙ ∙-idl _ ∙ ∙-elimr (∙-idl _ ∙ ∙-idl _ ∙ ∙-idr _ ∙ ∙-idl _ ∙ ∙-idl _ ∙ ∙-idl _))
188 | ∙ ap (sym ∘ merid) (θS n p)
189 |
190 | cⁿ⁻¹ : ∀ n → (p : Sⁿ⁻¹ n) → Tⁿ⁻¹ n p → p ≡ Equiv.to (antipodeⁿ⁻¹ n) p
191 | cⁿ⁻¹ n p t = sym (θN n p) ∙ ap (θⁿ⁻¹ n p .fst) (merid t) ∙ θS n p
192 |
193 | flipΣⁿ : ∀ n → Sⁿ⁻¹ n → Sⁿ⁻¹ n
194 | flipΣⁿ zero = id
195 | flipΣⁿ (suc n) = if⁺ even-or-odd n then flipΣ else id
196 |
197 | flipΣⁿ⁺² : ∀ n → map (map (flipΣⁿ n)) ≡ flipΣⁿ (suc (suc n))
198 | flipΣⁿ⁺² zero = ap map map-id ∙ map-id
199 | flipΣⁿ⁺² (suc n) with even-or-odd n
200 | ... | inl e = ap map rotateΣ ∙ rotateΣ
201 | ... | inr o = ap map map-id ∙ map-id
202 |
203 | antipode≡flip : ∀ n → Equiv.to (antipodeⁿ⁻¹ n) ≡ flipΣⁿ n
204 | antipode≡flip zero = refl
205 | antipode≡flip (suc zero) = ap (flipΣ ∘_) map-id
206 | antipode≡flip (suc (suc n)) =
207 | flipΣ ∘ map (flipΣ ∘ map (antipodeⁿ⁻¹ n .fst)) ≡⟨ flipΣ ∘⟨ map-∘ ⟩
208 | flipΣ ∘ map flipΣ ∘ map (map (antipodeⁿ⁻¹ n .fst)) ≡⟨ flipΣ ∘⟨ rotateΣ ⟩∘ map _ ⟩
209 | flipΣ ∘ flipΣ ∘ map (map (antipodeⁿ⁻¹ n .fst)) ≡⟨ funext flipΣ-involutive ⟩∘⟨refl ⟩
210 | map (map (antipodeⁿ⁻¹ n .fst)) ≡⟨ ap (map ∘ map) (antipode≡flip n) ⟩
211 | map (map (flipΣⁿ n)) ≡⟨ flipΣⁿ⁺² n ⟩
212 | flipΣⁿ (suc (suc n)) ∎
213 |
214 | -- If the tangent bundle of the n-sphere admits a section for even n, then we get
215 | -- a homotopy between flipΣ and the identity.
216 | section→homotopy : ∀ n → ((p : Sⁿ⁻¹ n) → Tⁿ⁻¹ n p) → flipΣⁿ n ≡ id
217 | section→homotopy n sec = sym $ funext (λ p → cⁿ⁻¹ n p (sec p)) ∙ antipode≡flip n
218 |
219 | -- Now to prove that this in turn implies that n-1 is odd requires a bit of
220 | -- homotopy theory in order to define the degrees of (unpointed!) maps of spheres.
221 |
222 | degree∙ : ∀ n → (Sⁿ (suc n) →∙ Sⁿ (suc n)) → Int
223 | degree∙ zero f = ΩS¹≃integers .fst (ap (transport SuspS⁰≡S¹) (Ωⁿ≃Sⁿ-map 1 .fst f))
224 | degree∙ (suc n) = {! πₙ(Sⁿ) ≃ ℤ !}
225 |
226 | degree∙-map : ∀ n f → degree∙ (suc n) (map (f .fst) , refl) ≡ degree∙ n f
227 | degree∙-map n f = {! the isomorphisms above should be compatible with suspension !}
228 |
229 | degree∙-id : ∀ n → degree∙ n id∙ ≡ 1
230 | degree∙-id zero = refl
231 | degree∙-id (suc n) = ap (degree∙ (suc n)) p ∙∙ degree∙-map n id∙ ∙∙ degree∙-id n
232 | where
233 | p : id∙ ≡ (map id , refl)
234 | p = Σ-pathp (sym map-id) refl
235 |
236 | degree∙-flipΣ : ∀ n → degree∙ n flipΣ∙ ≡ -1
237 | degree∙-flipΣ zero = refl -- neat.
238 | degree∙-flipΣ (suc n) = ap (degree∙ (suc n)) p ∙∙ degree∙-map n flipΣ∙ ∙∙ degree∙-flipΣ n
239 | where
240 | p : flipΣ∙ ≡ (map flipΣ , refl)
241 | p = Σ-pathp (sym rotateΣ) (λ i j → merid N (~ i ∧ ~ j))
242 |
243 | -- In order to define degrees of unpointed maps, we show that the function that
244 | -- forgets the pointing of a map Sⁿ →∙ Sⁿ is a bijection (up to homotopy).
245 | -- For n = 1, this is due to the fact that S¹ is the delooping of an abelian
246 | -- group; for n > 1, we can use the fact that the n-sphere is simply connected.
247 | Sⁿ-class-injective
248 | : ∀ n f → (p q : f N ≡ N)
249 | → ∥ Path (Sⁿ (suc n) →∙ Sⁿ (suc n)) (f , p) (f , q) ∥
250 | Sⁿ-class-injective zero f p q = inc (S¹-cohomology.injective refl)
251 | where
252 | open ConcreteGroup
253 | Sⁿ⁼¹-concrete : ConcreteGroup lzero
254 | Sⁿ⁼¹-concrete .B = Sⁿ 1
255 | Sⁿ⁼¹-concrete .has-is-connected = is-connected→is-connected∙ (Sⁿ⁻¹-is-connected 2)
256 | Sⁿ⁼¹-concrete .has-is-groupoid = subst is-groupoid (sym SuspS⁰≡S¹) S¹-is-groupoid
257 |
258 | Sⁿ⁼¹≡S¹ : Sⁿ⁼¹-concrete ≡ S¹-concrete
259 | Sⁿ⁼¹≡S¹ = ConcreteGroup-path (Σ-path SuspS⁰≡S¹ refl)
260 |
261 | Sⁿ⁼¹-ab : is-concrete-abelian Sⁿ⁼¹-concrete
262 | Sⁿ⁼¹-ab = subst is-concrete-abelian (sym Sⁿ⁼¹≡S¹) S¹-concrete-abelian
263 |
264 | module S¹-cohomology = Equiv
265 | (first-concrete-abelian-group-cohomology
266 | Sⁿ⁼¹-concrete Sⁿ⁼¹-concrete Sⁿ⁼¹-ab)
267 | Sⁿ-class-injective (suc n) f p q = ap (f ,_) <$> simply-connected p q
268 |
269 | Sⁿ-class
270 | : ∀ n
271 | → ∥ (Sⁿ (suc n) →∙ Sⁿ (suc n)) ∥₀
272 | → ∥ (⌞ Sⁿ (suc n) ⌟ → ⌞ Sⁿ (suc n) ⌟) ∥₀
273 | Sⁿ-class n = ∥-∥₀-rec (hlevel 2) λ (f , _) → inc f
274 |
275 | Sⁿ-pointed≃unpointed
276 | : ∀ n
277 | → ∥ (Sⁿ (suc n) →∙ Sⁿ (suc n)) ∥₀
278 | ≃ ∥ (⌞ Sⁿ (suc n) ⌟ → ⌞ Sⁿ (suc n) ⌟) ∥₀
279 | Sⁿ-pointed≃unpointed n .fst = Sⁿ-class n
280 | Sⁿ-pointed≃unpointed n .snd = injective-surjective→is-equiv! (inj _ _) surj
281 | where
282 | inj : ∀ f g → Sⁿ-class n f ≡ Sⁿ-class n g → f ≡ g
283 | inj = elim! λ f ptf g ptg f≡g →
284 | ∥-∥₀-path.from do
285 | f≡g ← ∥-∥₀-path.to f≡g
286 | J (λ g _ → ∀ ptg → ∥ (f , ptf) ≡ (g , ptg) ∥)
287 | (Sⁿ-class-injective n f ptf)
288 | f≡g ptg
289 |
290 | surj : is-surjective (Sⁿ-class n)
291 | surj = ∥-∥₀-elim (λ _ → hlevel 2) λ f → do
292 | pointed ← connected (f N) N
293 | pure (inc (f , pointed) , refl)
294 |
295 | degree : ∀ n → (⌞ Sⁿ (suc n) ⌟ → ⌞ Sⁿ (suc n) ⌟) → Int
296 | degree n f = ∥-∥₀-rec (hlevel 2)
297 | (degree∙ n)
298 | (Equiv.from (Sⁿ-pointed≃unpointed n) (inc f))
299 |
300 | degree∙≡degree : ∀ n f∙ → degree n (f∙ .fst) ≡ degree∙ n f∙
301 | degree∙≡degree n f∙ = ap (∥-∥₀-rec _ _)
302 | (U.injective₂ {x = U.from (inc (f∙ .fst))} {y = inc f∙} (U.ε _) refl)
303 | where module U = Equiv (Sⁿ-pointed≃unpointed n)
304 |
305 | flip≠id : ∀ n → ¬ flipΣ ≡ id {A = Sⁿ⁻¹ (suc n)}
306 | flip≠id zero h = subst (Susp-elim _ ⊤ ⊥ (λ ())) (h $ₚ S) _
307 | flip≠id (suc n) h = negsuc≠pos $
308 | -1 ≡˘⟨ degree∙-flipΣ n ⟩
309 | degree∙ n flipΣ∙ ≡˘⟨ degree∙≡degree n _ ⟩
310 | degree n flipΣ ≡⟨ ap (degree n) h ⟩
311 | degree n id ≡⟨ degree∙≡degree n _ ⟩
312 | degree∙ n id∙ ≡⟨ degree∙-id n ⟩
313 | 1 ∎
314 |
315 | hairy-ball : ∀ n → ((p : Sⁿ⁻¹ n) → Tⁿ⁻¹ n p) → is-even n
316 | hairy-ball zero sec = ∣-zero
317 | hairy-ball (suc n) sec with even-or-odd n | section→homotopy (suc n) sec
318 | ... | inl e | h = absurd (flip≠id n h)
319 | ... | inr o | _ = o
320 | ```
321 |
--------------------------------------------------------------------------------
/src-1lab/Untruncate.agda:
--------------------------------------------------------------------------------
1 | open import 1Lab.Prelude
2 |
3 | -- The identity function on homogeneous types "factors" through the propositional truncation
4 | -- (https://homotopytypetheory.org/2013/10/28/the-truncation-map-_-%E2%84%95-%E2%80%96%E2%84%95%E2%80%96-is-nearly-invertible)
5 | module Untruncate where
6 |
7 | point : ∀ {ℓ} (X : Type ℓ) → X → Type∙ ℓ
8 | point X x = X , x
9 |
10 | is-homogeneous : ∀ {ℓ} → Type ℓ → Type (lsuc ℓ)
11 | is-homogeneous X = ∀ x y → point X x ≡ point X y
12 |
13 | ∥-∥-rec-const
14 | : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
15 | → (f : A → B)
16 | → (b : B)
17 | → (∀ x → b ≡ f x)
18 | → ∥ A ∥ → B
19 | ∥-∥-rec-const {A = A} {B} f b f-const x =
20 | ∥-∥-elim {P = λ _ → Singleton b} (λ _ → is-contr→is-prop (contr _ Singleton-is-contr))
21 | (λ x → f x , f-const x) x .fst
22 |
23 | module old {ℓ} (X : Type ℓ) (x : X) (hom : is-homogeneous X) where
24 | point' : ∥ X ∥ → Type∙ ℓ
25 | point' = ∥-∥-rec-const (point X) (point X x) (hom x)
26 |
27 | myst : (x : ∥ X ∥) → point' x .fst
28 | myst x = point' x .snd
29 |
30 | _ : myst ∘ inc ≡ id
31 | _ = refl
32 |
33 | -- Simplification by David Wärn https://gist.github.com/dwarn/31d7002a5ca8df0443b31501056e357f
34 | module new {ℓ : Level} {X : Type ℓ} where
35 | fam : ∥ X ∥ → n-Type ℓ 0
36 | fam = rec! λ x → el! (Singleton x)
37 |
38 | magic : X → X
39 | magic = fst ∘ centre ∘ is-tr ∘ fam ∘ inc
40 |
41 | _ : magic ≡ id
42 | _ = refl
43 |
--------------------------------------------------------------------------------
/src-1lab/YonedaColimit.agda:
--------------------------------------------------------------------------------
1 | open import Cat.Prelude
2 | open import Cat.Functor.Hom
3 | open import Cat.Functor.Base
4 | open import Cat.Functor.Constant
5 | open import Cat.Diagram.Colimit.Base
6 | open import Cat.Diagram.Limit.Base
7 | open import Cat.Diagram.Terminal
8 | open import Cat.Diagram.Initial
9 | open import Cat.Instances.Presheaf.Limits
10 | open import Cat.Instances.Presheaf.Exponentials
11 |
12 | import Cat.Reasoning
13 |
14 | open _=>_
15 | open make-is-colimit
16 |
17 | module YonedaColimit {o ℓ} (C : Precategory o ℓ) where
18 |
19 | open Cat.Reasoning C
20 |
21 | Δ1 : Terminal (PSh ℓ C)
22 | Δ1 = PSh-terminal _ C
23 |
24 | open Terminal Δ1
25 |
26 | よ-colimit : Colimit (よ C)
27 | よ-colimit = to-colimit (to-is-colimit colim) where
28 | colim : make-is-colimit (よ C) top
29 | colim .ψ c = !
30 | colim .commutes f = ext λ _ _ → refl
31 | colim .universal eta comm .η x _ = eta x .η x id
32 | colim .universal eta comm .is-natural x y f = ext λ _ →
33 | sym (comm f ηₚ y $ₚ id) ∙∙ ap (eta x .η y) id-comm ∙∙ eta x .is-natural _ _ f $ₚ id
34 | colim .factors eta comm = ext λ x f →
35 | sym (comm f ηₚ x $ₚ id) ∙ ap (eta _ .η x) (idr _)
36 | colim .unique eta comm univ' fac' = ext λ x _ → fac' x ηₚ x $ₚ id
37 |
38 | Δ0 : Initial (PSh ℓ C)
39 | Δ0 = {! Const ? !}
40 |
41 | よ-limit : Limit (よ C)
42 | よ-limit = to-limit (to-is-limit lim) where
43 | lim : make-is-limit (よ C) (Const (el! (Lift _ ⊥)))
44 | lim .make-is-limit.ψ c .η x ()
45 | lim .make-is-limit.ψ c .is-natural _ _ _ = ext λ ()
46 | lim .make-is-limit.commutes f = ext λ _ ()
47 | lim .make-is-limit.universal eps comm .η = {! !}
48 | lim .make-is-limit.universal eps comm .is-natural = {! !}
49 | lim .make-is-limit.factors = {! !}
50 | lim .make-is-limit.unique = {! !}
51 |
--------------------------------------------------------------------------------
/src-1lab/src-1lab.agda-lib:
--------------------------------------------------------------------------------
1 | name: cubical-experiments
2 | include: .
3 | depend:
4 | 1lab
5 | flags:
6 | --cubical
7 | --no-load-primitives
8 | --postfix-projections
9 | --allow-unsolved-metas
10 | --rewriting
11 | --guardedness
12 | --erasure
13 | -W noInteractionMetaBoundaries
14 | -W noUnsupportedIndexedMatch
15 |
--------------------------------------------------------------------------------
/src/DeMorKan.agda:
--------------------------------------------------------------------------------
1 | open import Cubical.Foundations.Prelude
2 |
3 | -- A silly attempt at implementing composition for the interval,
4 | -- for https://proofassistants.stackexchange.com/questions/2043/is-the-de-morgan-interval-kan
5 | module DeMorKan where
6 |
7 | -- The built-in I lives in its own "non-fibrant" universe, so Agda won't let
8 | -- us express partial elements and subtypes.
9 | -- Hence we define a "wrapper" HIT, but do not make use of its Kan structure!
10 | data Interval : Type where
11 | i0' : Interval
12 | i1' : Interval
13 | inI : i0' ≡ i1'
14 |
15 | module 2D (i j : I) where
16 | ⊔ : I
17 | ⊔ = ~ j ∨ i ∨ ~ i
18 | B L R : I → I
19 | B i = i ∨ ~ i --
20 | L j = i1 -- replace these with anything (as long as they agree on endpoints)
21 | R j = ~ j --
22 | horn : Partial ⊔ Interval
23 | horn (j = i0) = inI (B i)
24 | horn (i = i0) = inI (L j)
25 | horn (i = i1) = inI (R j)
26 | filler : Interval [ ⊔ ↦ horn ]
27 | filler = inS (inI ((~ j ∧ B i) ∨ (~ i ∧ L j) ∨ (i ∧ R j)))
28 |
29 | module 3D (i j k : I) where
30 | ⊔ : I
31 | ⊔ = ~ k ∨ ~ i ∨ i ∨ ~ j ∨ j
32 | B L R D U : I → I → I
33 | B i j = i0
34 | L j k = i0
35 | R j k = i0
36 | D i k = i0
37 | U i k = i0
38 | horn : Partial ⊔ Interval
39 | horn (k = i0) = inI (B i j)
40 | horn (i = i0) = inI (L j k)
41 | horn (i = i1) = inI (R j k)
42 | horn (j = i0) = inI (D i k)
43 | horn (j = i1) = inI (U i k)
44 | filler : Interval [ ⊔ ↦ horn ]
45 | filler = inS (inI ((~ k ∧ B i j) ∨ (~ i ∧ L j k) ∨ (i ∧ R j k) ∨ (~ j ∧ D i k) ∨ (j ∧ U i k)))
46 |
--------------------------------------------------------------------------------
/src/Erasure.agda:
--------------------------------------------------------------------------------
1 | open import Agda.Primitive renaming (Set to Type; Setω to Typeω)
2 | open import Relation.Binary.PropositionalEquality hiding ([_])
3 | open import Axiom.Extensionality.Propositional
4 | {-# BUILTIN REWRITE _≡_ #-}
5 |
6 | -- Investigating the erasure modality. See also ErasureOpen
7 | module Erasure where
8 |
9 | private variable
10 | a b : Level
11 | A : Type a
12 |
13 | -- The erased path induction principle J₀
14 |
15 | J₀-type =
16 | ∀ {a b} {@0 A : Type a} {@0 x : A} (B : (@0 y : A) → @0 x ≡ y → Type b)
17 | → {@0 y : A} (@0 p : x ≡ y) → B x refl → B y p
18 |
19 | -- The Erased monadic modality
20 |
21 | record Erased (@0 A : Type a) : Type a where
22 | constructor [_]
23 | field
24 | @0 erased : A
25 |
26 | open Erased
27 |
28 | η : {@0 A : Type a} → A → Erased A
29 | η x = [ x ]
30 |
31 | μ : {@0 A : Type a} → Erased (Erased A) → Erased A
32 | μ [ [ x ] ] = [ x ]
33 |
34 | -- Paths (Erased A) → Erased (Paths A)
35 | erased-cong : ∀ {a} {@0 A : Type a} {@0 x y : A} → [ x ] ≡ [ y ] → Erased (x ≡ y)
36 | erased-cong p = [ cong erased p ]
37 |
38 | -- Erased (Paths A) → Paths (Erased A) ("erasure extensionality")
39 | []-cong-type = ∀ {a} {@0 A : Type a} {@0 x y : A} → Erased (x ≡ y) → [ x ] ≡ [ y ]
40 |
41 | -- J₀ and []-cong (with their respective computation rules) are interderivable
42 |
43 | module J₀→[]-cong where
44 | postulate
45 | J₀ : J₀-type
46 | J₀-refl
47 | : ∀ {a b} {@0 A : Type a} {@0 x : A} (B : (@0 y : A) → @0 x ≡ y → Type b) (r : B x refl)
48 | → J₀ B refl r ≡ r
49 | {-# REWRITE J₀-refl #-}
50 |
51 | []-cong : []-cong-type
52 | []-cong {x} [ p ] = J₀ (λ y _ → [ x ] ≡ [ y ]) p refl
53 |
54 | []-cong-refl
55 | : ∀ {a} {@0 A : Type a} {@0 x : A}
56 | → []-cong {x = x} [ refl ] ≡ refl
57 | []-cong-refl = refl
58 |
59 | module []-cong→J₀ where
60 | postulate
61 | []-cong : []-cong-type
62 | []-cong-refl
63 | : ∀ {a} {@0 A : Type a} {@0 x : A}
64 | → []-cong {x = x} [ refl ] ≡ refl
65 | {-# REWRITE []-cong-refl #-}
66 |
67 | -- []-cong μ
68 | -- Erased (Paths (Erased A)) → Paths (Erased (Erased A)) → Paths (Erased A)
69 | stable-≡ : ∀ {@0 A : Type a} {x y : Erased A} → Erased (x ≡ y) → x ≡ y
70 | stable-≡ p = cong μ ([]-cong p)
71 |
72 | -- η []-cong erased-cong
73 | -- Paths A → Erased (Paths A) → Paths (Erased A) → Erased (Paths A)
74 | -- Erased (Paths A) → Erased (Paths A)
75 | -- id
76 | []-cong-section'
77 | : ∀ {@0 A : Type a} {@0 x y : A} (p : x ≡ y)
78 | → erased-cong ([]-cong (η p)) ≡ η p
79 | []-cong-section' refl = refl
80 |
81 | -- We can cancel out η by unique elimination and stability of paths in Erased
82 | []-cong-section
83 | : ∀ {@0 A : Type a} {@0 x y : A} (@0 p : x ≡ y)
84 | → erased-cong ([]-cong [ p ]) ≡ [ p ]
85 | []-cong-section p = stable-≡ [ []-cong-section' p ]
86 |
87 | J₀ : J₀-type
88 | J₀ B {y} p r = subst (λ ([ p ]) → B y p) ([]-cong-section p) b'
89 | where
90 | b' : B y (cong erased ([]-cong [ p ]))
91 | b' = J (λ ([ y ]) p → B y (cong erased p)) ([]-cong [ p ]) r
92 |
93 | J₀-refl
94 | : ∀ {a b} {@0 A : Type a} {@0 x : A} (B : (@0 y : A) → @0 x ≡ y → Type b) (r : B x refl)
95 | → J₀ B refl r ≡ r
96 | J₀-refl B r = refl
97 |
98 | -- Function extensionality implies erasure extensionality
99 | module funext→[]-cong where
100 | postulate
101 | funext : ∀ {a b} → Extensionality a b
102 |
103 | -- Direct proof, extracted from "Logical properties of a modality for erasure" (Danielsson 2019)
104 |
105 | -- id : Paths (Erased A) → Paths (Erased A)
106 | -- → {funext}
107 | -- Paths (Paths (Erased A) → Erased A)
108 | -- → {uniquely eliminating}
109 | -- Paths (Erased (Paths (Erased A)) → Erased A)
110 | -- → {apply p}
111 | -- Paths (Erased A)
112 | stable-≡ : ∀ {@0 A : Type a} {x y : Erased A} → Erased (x ≡ y) → x ≡ y
113 | stable-≡ {A} {x} {y} [ p ] =
114 | cong (λ (f : x ≡ y → Erased A) → [ f p .erased ])
115 | (funext (λ (p : x ≡ y) → p))
116 |
117 | -- η stable-≡
118 | -- Erased (Paths A) → Erased (Paths (Erased A)) → Paths (Erased A)
119 | []-cong : []-cong-type
120 | []-cong [ p ] = stable-≡ [ cong η p ]
121 |
122 | -- Alternative proof: ignoring some details, the types of funext and []-cong look very similar:
123 | -- funext : Functions (Paths A) → Paths (Functions A)
124 | -- []-cong : Erased (Paths A) → Paths (Erased A)
125 | --
126 | -- If we have inductive types with erased constructors, then we can
127 | -- present erasure as an *open modality* generated by the subterminal
128 | -- object with a single erased point (see ErasureOpen):
129 |
130 | data Compiling : Type where
131 | @0 compiling : Compiling
132 |
133 | ○_ : Type a → Type a
134 | ○ A = Compiling → A
135 |
136 | ○'_ : ○ Type a → Type a
137 | ○' A = (n : Compiling) → A n
138 |
139 | E→○ : {A : ○ Type a} → Erased (A compiling) → ○' A
140 | E→○ a compiling = a .erased
141 |
142 | ○→E : {A : ○ Type a} → ○' A → Erased (A compiling)
143 | ○→E f .erased = f compiling
144 |
145 | E→○→E : {A : ○ Type a} → (a : Erased (A compiling)) → ○→E (E→○ {A = A} a) ≡ a
146 | E→○→E _ = refl
147 |
148 | -- We don't actually need this
149 | ○→E→○ : {A : ○ Type a} → (f : ○' A) → E→○ (○→E f) ≡ f
150 | ○→E→○ f = funext (E→○ [ refl {x = f compiling} ])
151 |
152 | -- Since Erased is (equivalent to) a function type, erasure extensionality/[]-cong
153 | -- is a special case of function extensionality:
154 | --
155 | -- funext
156 | -- Erased (Paths A) ≃ (Compiling → Paths A) → Paths (Compiling → A) ≃ Paths (Erased A)
157 | []-cong' : []-cong-type
158 | []-cong' {A} {x} {y} p = cong ○→E x'≡y'
159 | where
160 | x' y' : ○' E→○ [ A ]
161 | x' = E→○ [ x ]
162 | y' = E→○ [ y ]
163 |
164 | x'≡y' : x' ≡ y'
165 | x'≡y' = funext (E→○ p)
166 |
--------------------------------------------------------------------------------
/src/NaiveFunext.agda:
--------------------------------------------------------------------------------
1 | {-# OPTIONS --without-K #-}
2 | open import Agda.Primitive renaming (Set to Type)
3 | open import Data.Product
4 | open import Data.Product.Properties
5 | open import Relation.Binary.PropositionalEquality
6 |
7 | -- Naïve function extensionality implies function extensionality (HoTT book exercise 4.9).
8 | -- This is actually weaker as we assume ~ → ≡ for *dependent* functions.
9 | module NaiveFunext where
10 |
11 | private variable
12 | ℓ ℓ' : Level
13 | A : Type ℓ
14 | B : A → Type ℓ
15 | f g : (a : A) → B a
16 |
17 | _~_ : (f g : (a : A) → B a) → Type _
18 | f ~ g = ∀ a → f a ≡ g a
19 |
20 | happly : f ≡ g → f ~ g
21 | happly {f = f} p = subst (λ x → f ~ x) p λ _ → refl
22 |
23 | cong-proj₂ : ∀ {a b} {c : B a} {d : B b} → (p : (a , c) ≡ (b , d)) → subst B (cong proj₁ p) c ≡ d
24 | cong-proj₂ {c = c} refl = refl
25 |
26 | singleton-is-contr : ∀ {a : A} {s : Σ A (a ≡_)} → (a , refl) ≡ s
27 | singleton-is-contr {s = _ , refl} = refl
28 |
29 | module _
30 | (ext : ∀ {ℓ ℓ'} {A : Type ℓ} {B : A → Type ℓ'} {f g : (a : A) → B a} → f ~ g → f ≡ g)
31 | where
32 |
33 | module _ (f : (a : A) → B a) where
34 | from : ((a : A) → Σ _ (f a ≡_)) → Σ _ (f ~_)
35 | from p = (λ a → p a .proj₁) , (λ a → p a .proj₂)
36 |
37 | to : Σ _ (f ~_) → ((a : A) → Σ _ (f a ≡_))
38 | to g = λ a → g .proj₁ a , g .proj₂ a
39 |
40 | -- Homotopies form an identity system, which is equivalent to function extensionality.
41 | htpy-is-contr : (g : Σ _ (f ~_)) → (f , λ _ → refl) ≡ g
42 | htpy-is-contr g = cong from p
43 | where
44 | p : (λ a → f a , refl) ≡ to g
45 | p = ext λ _ → singleton-is-contr
46 |
--------------------------------------------------------------------------------
/src/NatChurchMonoid.agda:
--------------------------------------------------------------------------------
1 | open import Cubical.Algebra.Monoid
2 | open import Cubical.Algebra.Monoid.Instances.Nat
3 | open import Cubical.Algebra.Semigroup
4 | open import Cubical.Data.Nat
5 | open import Cubical.Data.Sigma
6 | open import Cubical.Foundations.Prelude
7 | open import Cubical.Foundations.Function
8 | open import Cubical.Foundations.Isomorphism
9 | open import Cubical.Foundations.Structure
10 |
11 | -- ℕ ≃ (m : Monoid) → ⟨ m ⟩ → ⟨ m ⟩
12 | module NatChurchMonoid where
13 |
14 | MEndo : Type₁
15 | MEndo = (m : Monoid ℓ-zero) → ⟨ m ⟩ → ⟨ m ⟩
16 |
17 | isNatural : MEndo → Type₁
18 | isNatural me = {m1 m2 : Monoid ℓ-zero} (f : MonoidHom m1 m2) → me m2 ∘ f .fst ≡ f .fst ∘ me m1
19 |
20 | isPropIsNatural : (me : MEndo) → isProp (isNatural me)
21 | isPropIsNatural me a b i {m1} {m2} f j x = m2 .snd .MonoidStr.isMonoid .IsMonoid.isSemigroup .IsSemigroup.is-set (me m2 (f .fst x)) (f .fst (me m1 x)) (funExt⁻ (a f) x) (funExt⁻ (b f) x) i j
22 |
23 | MEndoNatural : Type₁
24 | MEndoNatural = Σ MEndo isNatural
25 |
26 | -- A generalised Church encoding for ℕ. This boils down to the fact that the forgetful functor
27 | -- U : Mon → Set is represented by ℕ ≃ F 1, followed by the Yoneda lemma.
28 | ℕ≃MEndoNatural : Iso ℕ MEndoNatural
29 | ℕ≃MEndoNatural = iso mtimes on1 mtimes-on1 on1-mtimes where
30 |
31 | mtimes : ℕ → MEndoNatural
32 | mtimes zero .fst (_ , monoidstr ε _·_ m) = (λ _ → ε)
33 | mtimes zero .snd f = funExt λ _ → sym (f .snd .IsMonoidHom.presε)
34 | mtimes (suc n) .fst ms@(t , monoidstr ε _·_ m) = (λ x → x · mtimes n .fst ms x)
35 | mtimes (suc n) .snd {m1} {m2@(_ , monoidstr _ _·_ m)} f = funExt λ x → cong (f .fst x ·_) (λ i → mtimes n .snd f i x) ∙ sym (f .snd .IsMonoidHom.pres· x (mtimes n .fst m1 x))
36 |
37 | mtimes-hom : (m : Monoid ℓ-zero) (x : ⟨ m ⟩) → MonoidHom NatMonoid m
38 | mtimes-hom m x = (λ n → mtimes n .fst m x) , monoidequiv refl (λ n n' → mtimes-+ n n') where
39 | mtimes-+ : (n n' : ℕ) {m : Monoid ℓ-zero} {x : ⟨ m ⟩} → mtimes (n + n') .fst m x ≡ m .snd .MonoidStr._·_ (mtimes n .fst m x) (mtimes n' .fst m x)
40 | mtimes-+ zero n' {m} = sym (m .snd .MonoidStr.isMonoid .IsMonoid.·IdL _)
41 | mtimes-+ (suc n) n' {m} {x} = cong (m .snd .MonoidStr._·_ x) (mtimes-+ n n') ∙ m .snd .MonoidStr.isMonoid .IsMonoid.isSemigroup .IsSemigroup.·Assoc _ _ _
42 |
43 | on1 : MEndoNatural → ℕ
44 | on1 me = me .fst NatMonoid 1
45 |
46 | on1-mtimes : (n : ℕ) → on1 (mtimes n) ≡ n
47 | on1-mtimes zero = refl
48 | on1-mtimes (suc n) = cong suc (on1-mtimes n)
49 |
50 | mtimes-on1 : (me : MEndoNatural) → mtimes (on1 me) ≡ me
51 | mtimes-on1 me = Σ≡Prop isPropIsNatural (λ i m x → p m x i) where
52 | p : (m : Monoid ℓ-zero) (x : ⟨ m ⟩) → mtimes (on1 me) .fst m x ≡ me .fst m x
53 | p m x = sym (funExt⁻ (me .snd (mtimes-hom m x)) 1)
54 | ∙ cong (me .fst m) (m .snd .MonoidStr.isMonoid .IsMonoid.·IdR _)
55 |
--------------------------------------------------------------------------------
/src/Shapes.agda:
--------------------------------------------------------------------------------
1 | open import Cubical.Foundations.Prelude
2 | open import Cubical.Foundations.Path
3 | open import Cubical.Foundations.Isomorphism renaming (Iso to _≃_)
4 | open import Cubical.Foundations.Univalence
5 | open import Cubical.Data.Unit renaming (Unit to ⊤)
6 | open import Cubical.Data.Sigma
7 | open import Cubical.Data.Int
8 | open import Cubical.Relation.Nullary
9 |
10 | -- —
11 | data Interval : Type where
12 | l : Interval
13 | r : Interval
14 | seg : l ≡ r
15 |
16 | Interval-isContr : isContr Interval
17 | Interval-isContr = l , paths where
18 | paths : (x : Interval) → l ≡ x
19 | paths l = refl
20 | paths r = seg
21 | paths (seg i) j = seg (i ∧ j)
22 |
23 | Interval-loops : (x : Interval) → x ≡ x
24 | Interval-loops l = refl
25 | Interval-loops r = refl
26 | Interval-loops (seg i) j = seg i
27 |
28 | -- ○
29 | data S¹ : Type where
30 | base : S¹
31 | loop : base ≡ base
32 |
33 | S¹→⊤ : S¹ → ⊤
34 | S¹→⊤ base = tt
35 | S¹→⊤ (loop i) = tt
36 | ⊤→S¹ : ⊤ → S¹
37 | ⊤→S¹ tt = base
38 | ⊤→S¹→⊤ : (t : ⊤) → S¹→⊤ (⊤→S¹ t) ≡ t
39 | ⊤→S¹→⊤ tt = refl
40 | -- S¹→⊤→S¹ : (x : S¹) → ⊤→S¹ (S¹→⊤ x) ≡ x
41 | -- S¹→⊤→S¹ base = refl
42 | -- S¹→⊤→S¹ (loop i) j = {! IMPOSSIBLE the point doesn't retract onto the circle! !}
43 |
44 | always-loop : (x : S¹) → x ≡ x
45 | always-loop base = loop
46 | always-loop (loop i) j =
47 | hcomp (λ where k (i = i0) → loop (j ∨ ~ k)
48 | k (i = i1) → loop (j ∧ k)
49 | k (j = i0) → loop (i ∨ ~ k)
50 | k (j = i1) → loop (i ∧ k))
51 | base
52 |
53 | loop-induction : {ℓ : Level} {P : base ≡ base → Type ℓ}
54 | → (pprop : ∀ p → isProp (P p))
55 | → (prefl : P refl)
56 | → (ploop : ∀ p → P p → P (p ∙ loop))
57 | → (ppool : ∀ p → P p → P (p ∙ sym loop))
58 | → (p : base ≡ base) → P p
59 | loop-induction {ℓ} {P} pprop prefl ploop ppool = J Q prefl
60 | where
61 | bridge : PathP (λ i → base ≡ loop i → Type ℓ) P P
62 | bridge = toPathP (funExt λ p → isoToPath
63 | (iso (λ x → subst P (compPathr-cancel _ _) (ploop _ x))
64 | (ppool p)
65 | (λ _ → pprop _ _ _)
66 | (λ _ → pprop _ _ _)))
67 | Q : (x : S¹) → base ≡ x → Type ℓ
68 | Q base p = P p
69 | Q (loop i) p = bridge i p
70 |
71 | data Bool₁ : Type₁ where
72 | false true : Bool₁
73 |
74 | S¹⋆ : Σ Type (λ A → A)
75 | S¹⋆ = S¹ , base
76 |
77 | flip : S¹ → S¹
78 | flip base = base
79 | flip (loop i) = loop (~ i)
80 | flip≡ : S¹ ≡ S¹
81 | flip≡ = isoToPath (iso flip flip inv inv) where
82 | inv : section flip flip
83 | inv base = refl
84 | inv (loop i) = refl
85 | flip⋆ : S¹⋆ ≡ S¹⋆
86 | flip⋆ i = flip≡ i , base≡base i where
87 | base≡base : PathP (λ i → flip≡ i) base base
88 | base≡base = ua-gluePath _ refl
89 |
90 | Cover : S¹ → Type
91 | Cover base = ℤ
92 | Cover (loop i) = sucPathℤ i
93 |
94 | S¹⋆-auto : (S¹⋆ ≡ S¹⋆) ≡ Bool₁
95 | S¹⋆-auto = isoToPath (iso to from sec ret) where
96 | isPos : ℤ → Bool₁
97 | isPos (pos _) = true
98 | isPos _ = false
99 | to : S¹⋆ ≡ S¹⋆ → Bool₁
100 | to p = isPos (transport (λ i → Cover (loop' i)) 0) where
101 | loop' : base ≡ base
102 | loop' i = comp (λ j → p j .fst)
103 | (λ where j (i = i0) → p j .snd
104 | j (i = i1) → p j .snd)
105 | (loop i)
106 | from : Bool₁ → S¹⋆ ≡ S¹⋆
107 | from false = flip⋆
108 | from true = refl
109 | sec : section to from
110 | sec false = refl
111 | sec true = refl
112 | ret : retract to from
113 | ret p = {! !}
114 |
115 | -- ●
116 | data D² : Type where
117 | base² : D²
118 | loop² : base² ≡ base²
119 | disk : refl ≡ loop²
120 |
121 | D²-isContr : isContr D²
122 | D²-isContr = base² , paths where
123 | paths : (x : D²) → base² ≡ x
124 | paths base² = refl
125 | paths (loop² i) j = disk j i
126 | paths (disk i j) k = disk (i ∧ k) j
127 |
128 | D²-isProp : isProp D²
129 | D²-isProp x y = sym (D²-isContr .snd x) ∙ D²-isContr .snd y
130 |
131 | data coeq (X : Type) : Type where
132 | inc : X → coeq X
133 | eq : ∀ x → inc x ≡ inc x
134 |
135 | lemma : ∀ X → coeq X ≃ (X × S¹)
136 | lemma X = iso to from to-from from-to where
137 | to : coeq X → X × S¹
138 | to (inc x) = x , base
139 | to (eq x i) = x , loop i
140 | from : X × S¹ → coeq X
141 | from (x , base) = inc x
142 | from (x , loop i) = eq x i
143 | to-from : ∀ x → to (from x) ≡ x
144 | to-from (_ , base) = refl
145 | to-from (_ , loop i) = refl
146 | from-to : ∀ x → from (to x) ≡ x
147 | from-to (inc x) = refl
148 | from-to (eq x i) = refl
149 |
--------------------------------------------------------------------------------
/src/Torus.agda:
--------------------------------------------------------------------------------
1 | module Torus where
2 |
3 | open import Cubical.Foundations.Prelude
4 | open import Cubical.Foundations.Isomorphism
5 | open import Cubical.Foundations.Equiv
6 | open import Cubical.Foundations.GroupoidLaws
7 | open import Cubical.HITs.Torus
8 |
9 | private
10 | variable
11 | ℓ : Level
12 | A : Type ℓ
13 |
14 | -- 🍩
15 | data T² : Type where
16 | base : T²
17 | p q : base ≡ base
18 | surf : p ∙ q ≡ q ∙ p
19 |
20 | hcomp-inv : {φ : I} (u : I → Partial φ A) (u0 : A [ φ ↦ u i1 ])
21 | → hcomp u (hcomp (λ k → u (~ k)) (outS u0)) ≡ outS u0
22 | hcomp-inv u u0 i = hcomp-equivFiller (λ k → u (~ k)) u0 (~ i)
23 |
24 | T²≃Torus : T² ≃ Torus
25 | T²≃Torus = isoToEquiv (iso to from to-from from-to)
26 | where
27 | sides : {a : A} (p1 p2 : a ≡ a) (i j k : I) → Partial (i ∨ ~ i ∨ j ∨ ~ j) A
28 | sides p1 p2 i j k (i = i0) = compPath-filler p2 p1 (~ k) j
29 | sides p1 p2 i j k (i = i1) = compPath-filler' p1 p2 (~ k) j
30 | sides p1 p2 i j k (j = i0) = p1 (i ∧ k)
31 | sides p1 p2 i j k (j = i1) = p1 (i ∨ ~ k)
32 |
33 | to : T² → Torus
34 | to base = point
35 | to (p i) = line1 i
36 | to (q j) = line2 j
37 | to (surf i j) = hcomp (λ k → sides line1 line2 (~ i) j (~ k)) (square (~ i) j)
38 |
39 | from : Torus → T²
40 | from point = base
41 | from (line1 i) = p i
42 | from (line2 j) = q j
43 | from (square i j) = hcomp (sides p q i j) (surf (~ i) j)
44 |
45 | to-from : ∀ x → to (from x) ≡ x
46 | to-from point = refl
47 | to-from (line1 i) = refl
48 | to-from (line2 i) = refl
49 | to-from (square i j) = hcomp-inv (sides line1 line2 i j) (inS (square i j))
50 |
51 | from-to : ∀ x → from (to x) ≡ x
52 | from-to base = refl
53 | from-to (p i) = refl
54 | from-to (q i) = refl
55 | from-to (surf i j) = {! hcomp-inv (λ k → sides p q (~ i) j (~ k)) (inS (surf i j)) !}
56 | -- see https://github.com/agda/cubical/pull/912 for the full proof
57 |
--------------------------------------------------------------------------------
/src/src.agda-lib:
--------------------------------------------------------------------------------
1 | name: cubical-experiments
2 | include: .
3 | depend:
4 | standard-library
5 | cubical
6 | flags:
7 | --cubical
8 | --no-import-sorts
9 | --postfix-projections
10 | --hidden-argument-puns
11 | --allow-unsolved-metas
12 | --rewriting
13 | --guardedness
14 | --erasure
15 | -W noInteractionMetaBoundaries
16 | -W noUnsupportedIndexedMatch
17 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: JuliaMono;
3 | src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono/webfonts/JuliaMono-Medium.woff2");
4 | font-display: swap;
5 | }
6 |
7 | @font-face {
8 | font-family: JuliaMono;
9 | font-weight: bold;
10 | src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono/webfonts/JuliaMono-ExtraBold.woff2");
11 | font-display: swap;
12 | }
13 |
14 | :root {
15 | --background: #080709;
16 | --foreground: white;
17 | --accent: #c15cff;
18 | --comment: hsl(0, 0%, 60%);
19 | --defined: var(--foreground);
20 | --literal: var(--accent);
21 | --keyword: var(--foreground);
22 | --symbol: var(--foreground);
23 | --bound: #c59efd;
24 | --module: var(--literal);
25 | --constructor: var(--literal);
26 | }
27 |
28 | ::selection {
29 | background-color: var(--accent);
30 | color: white;
31 | }
32 |
33 | body {
34 | margin: 0 15%;
35 | font-family: sans-serif;
36 | text-align: justify;
37 | background-color: var(--background);
38 | color: var(--foreground);
39 | }
40 |
41 | pre {
42 | /* Otherwise Firefox takes ages trying to justify blocks... */
43 | text-align: initial;
44 | }
45 |
46 | pre, code {
47 | font-family: JuliaMono, monospace;
48 | }
49 |
50 | details {
51 | border-inline-start: 4px solid var(--accent);
52 | padding-inline-start: 8px;
53 | }
54 |
55 | details > summary::after {
56 | content: '(click to unfold)';
57 | color: var(--comment);
58 | }
59 |
60 | details[open] > summary::after {
61 | content: '(click to fold)';
62 | }
63 |
64 | .anchor::before {
65 | content: '🔗';
66 | display: inline-block;
67 | font-size: 80%;
68 | margin-left: 10px;
69 | opacity: 0.3;
70 | }
71 |
72 | .anchor:hover {
73 | text-decoration: none;
74 | }
75 |
76 | h1:hover > .anchor::before, h2:hover > .anchor::before, h3:hover > .anchor::before, h4:hover > .anchor::before, h5:hover > .anchor::before, h6:hover > .anchor::before {
77 | opacity: 1;
78 | }
79 |
80 | :any-link {
81 | text-decoration: none;
82 | color: var(--module);
83 | }
84 |
85 | /* Aspects. */
86 | .Agda .Comment { color: var(--comment) }
87 | .Agda .Background { }
88 | .Agda .Markup { }
89 | .Agda .Keyword { color: var(--keyword); font-weight: bold; }
90 | .Agda .String { color: var(--literal) }
91 | .Agda .Number { color: var(--literal) }
92 | .Agda .Symbol { color: var(--symbol) }
93 | .Agda .PrimitiveType { color: var(--defined) }
94 | .Agda .Pragma { color: var(--keyword) }
95 | .Agda .Operator {}
96 | .Agda .Hole { background: #490764 }
97 | .Agda .Macro { color: var(--defined) }
98 |
99 | /* NameKinds. */
100 | .Agda .Bound { color: var(--bound) }
101 | .Agda .Generalizable { color: var(--bound) }
102 | .Agda .InductiveConstructor { color: var(--constructor) }
103 | .Agda .CoinductiveConstructor { color: var(--constructor) }
104 | .Agda .Datatype { color: var(--defined) }
105 | .Agda .Field { color: var(--constructor) }
106 | .Agda .Function { color: var(--defined) }
107 | .Agda .Module { color: var(--module) }
108 | .Agda .Postulate { color: var(--defined) }
109 | .Agda .Primitive { color: var(--defined) }
110 | .Agda .Record { color: var(--defined) }
111 |
112 | /* OtherAspects. */
113 | .Agda .DottedPattern {}
114 | .Agda .UnsolvedMeta { color: var(--foreground); background: yellow }
115 | .Agda .UnsolvedConstraint { color: var(--foreground); background: yellow }
116 | .Agda .TerminationProblem { color: var(--foreground); background: #FFA07A }
117 | .Agda .IncompletePattern { color: var(--foreground); background: #F5DEB3 }
118 | .Agda .Error { color: red; text-decoration: underline }
119 | .Agda .TypeChecks { color: var(--foreground); background: #ADD8E6 }
120 | .Agda .Deadcode { color: var(--foreground); background: #808080 }
121 | .Agda .ShadowingInTelescope { color: var(--foreground); background: #808080 }
122 |
123 | /* Standard attributes. */
124 | .Agda a { text-decoration: none }
125 | .Agda a[href]:hover { background-color: #444; }
126 | .Agda [href].hover-highlight { background-color: #444; }
127 |
--------------------------------------------------------------------------------