diff --git a/plugin/remark-agda.ts b/plugin/remark-agda.ts index 02b01fa..8e4c300 100644 --- a/plugin/remark-agda.ts +++ b/plugin/remark-agda.ts @@ -36,8 +36,6 @@ const remarkAgda: RemarkPlugin = ({ base, publicDir }: Options) => { const tempDir = mkdtempSync(join(tmpdir(), "agdaRender.")); const agdaOutDir = join(tempDir, "output"); - const agdaOutFilename = parse(path).base.replace(/\.lagda.md/, ".md"); - const agdaOutFile = join(agdaOutDir, agdaOutFilename); mkdirSync(agdaOutDir, { recursive: true }); const childOutput = spawnSync( @@ -164,6 +162,8 @@ const remarkAgda: RemarkPlugin = ({ base, publicDir }: Options) => { idx += 1; }); } catch (e) { + // TODO: Figure out a way to handle this correctly + // Possibly by diffing? console.log( "Mismatch in number of args. Perhaps there was an empty block?", ); diff --git a/src/content/posts/2024-09-18-hcomp/index.lagda.md b/src/content/posts/2024-09-18-hcomp/index.lagda.md index f90c57d..85b6e99 100644 --- a/src/content/posts/2024-09-18-hcomp/index.lagda.md +++ b/src/content/posts/2024-09-18-hcomp/index.lagda.md @@ -1,21 +1,37 @@ --- -title: Examples of hcomp +title: Visual examples of hcomp slug: 2024-09-18-hcomp date: 2024-09-18T04:07:13-05:00 tags: [hott, cubical] draft: true --- -**hcomp** is a primitive operation in cubical type theory. +**hcomp** is a primitive operation in [cubical type theory][cchm] that completes the _lid_ of an incomplete cube, given the bottom face and some number of side faces. + +[CCHM]: https://arxiv.org/abs/1611.02108 + +
+Imports ``` {-# OPTIONS --cubical --allow-unsolved-metas #-} module 2024-09-18-hcomp.index where open import Cubical.Foundations.Prelude hiding (isProp→isSet) +open import Cubical.Foundations.Equiv.Base +open import Cubical.Foundations.Isomorphism open import Cubical.Core.Primitives +open import Cubical.HITs.Susp.Base +open import Cubical.HITs.S1.Base +open import Data.Bool.Base ``` -Intuitively, hcomp can be understood as the composition operation. +
+ +## Two-dimensional case + +In two dimensions, hcomp can be understood as the double-composition operation. +"Single" composition (between two paths rather than three) is typically implemented as a double composition with the left leg as $\mathsf{refl}$. +Without the double composition, this looks like: ``` path-comp : {A : Type} {x y z : A} → x ≡ y → y ≡ z → x ≡ z @@ -26,6 +42,8 @@ path-comp {x = x} p q i = in hcomp u (p i) ``` +The `(i = i0)` case in this case is $\mathsf{refl}_x(j)$ which is definitionally equal to $x$. + ## Example: $\mathsf{isProp}(A) \rightarrow \mathsf{isSet}(A)$ Suppose we want to prove that all mere propositions (h-level 1) are sets (h-level 2). @@ -46,8 +64,10 @@ So essentially, the final goal is a square with these boundaries: ![](./goal.jpg) -Our goal is to find out what completes this square. -Well, one way to complete a square is to treat it as the top face of a cube and use $\mathsf{hcomp}$. +Our goal is to fill this square in. +Well, what is a square but a missing face in a 3-dimensional cube? +Let's draw out what this cube looks like, and then have $\mathsf{hcomp}$ give us the top face. +Before getting started, let's familiarize ourselves with the dimensions we're working with: * $i$ is the left-right dimension, the one that $p$ and $q$ work over * $j$ is the dimension of our final path between $p \equiv q$. @@ -93,4 +113,100 @@ Hooray! Agda is happy with this. Let's move on to a more complicated example. -## Example: $\Sigma \mathbb{2} \rightarrow S^1$ +## Example: $\Sigma \mathbb{2} \simeq S^1$ + +Suspensions are an example of a higher inductive type. +It can be shown that spheres can be iteratively defined in terms of suspensions. + +Since the $0$-sphere is just two points (solutions to $\| \bm{x} \|_2 = 1$ in 1 dimension), we can show that a suspension over this is equivalent to the classic $1$-sphere, or the circle. + +Let's state the lemma: + +``` +Σ2≃S¹ : Susp Bool ≃ S¹ +``` + +Equivalences can be generated from isomorphisms: + +``` +Σ2≃S¹ = isoToEquiv (iso f g fg gf) where +``` + +In this model, we're going to define $f$ and $g$ by having both the north and south poles be squished into one side. +The choice of side is arbitrary, so I'll choose $\mathsf{true}$. +This way, $\mathsf{true}$ is suspended into the $\mathsf{refl}$ path, and $\mathsf{false}$ is suspended into the $\mathsf{loop}$. + + + + + + + + + + + +
+ +``` + f : Susp Bool → S¹ + f north = base + f south = base + f (merid true i) = base + f (merid false i) = loop i +``` + + + +``` + g : S¹ → Susp Bool + g base = north + g (loop i) = (merid false ∙ sym (merid true)) i + + +``` + +
+ +Now, the fun part is to show the isomorphisms. +Starting with the first, let's show $f(g(s)) \equiv s$. +The base case is easily handled by $\mathsf{refl}$. + +``` + fg : (s : S¹) → f (g s) ≡ s + fg base = refl +``` + +The loop case is trickier. Let's solve it algebraically first: + +$$ +\begin{align*} +\mathsf{ap}_f(\mathsf{ap}_g(\mathsf{loop})) &\equiv \mathsf{loop} \\ +\mathsf{ap}_f(\mathsf{merid} \; \mathsf{false} \cdot (\mathsf{merid} \; \mathsf{true})^{-1}) &\equiv \mathsf{loop} \\ +\mathsf{ap}_f(\mathsf{merid} \; \mathsf{false}) \cdot \mathsf{ap}_f (\mathsf{merid} \; \mathsf{true})^{-1} &\equiv \mathsf{loop} \\ +\mathsf{loop} \cdot \mathsf{ap}_f (\mathsf{merid} \; \mathsf{true})^{-1} &\equiv \mathsf{loop} \\ +\mathsf{loop} \cdot \mathsf{refl}^{-1} &\equiv \mathsf{loop} \\ +\mathsf{loop} \cdot \mathsf{refl} &\equiv \mathsf{loop} \\ +\mathsf{loop} &\equiv \mathsf{loop} \\ +\end{align*} +$$ + +Between the second and third steps, I used functoriality of the $\mathsf{ap}$ operation. + +``` + fg (loop i) k = + let + leftFace = λ j → compPath-filler (λ i → f (merid false i)) (λ j → f (merid true (~ j))) j i + + u = λ j → λ where + (i = i0) → base + (i = i1) → f (merid true (~ j)) + (k = i0) → leftFace j + (k = i1) → loop i + in hcomp u (f (merid false i)) +``` + +``` + gf : (b : Susp Bool) → g (f b) ≡ b + gf b = {! !} +```