Skip to content

Commit c715dd7

Browse files
committed
more prose on assemblies
1 parent e5a8d14 commit c715dd7

12 files changed

+567
-95
lines changed

src/Cat/Instances/Assemblies.lagda.md

Lines changed: 145 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ open import Cat.Prelude
88
open import Data.Partial.Total
99
open import Data.Partial.Base
1010
11+
open import Realisability.PCA.Trivial
1112
open import Realisability.PCA
1213
1314
import 1Lab.Reflection as R
1415
15-
import Realisability.Data.Pair as Pair
16-
import Realisability.PCA.Sugar as Sugar
17-
import Realisability.Base as Logic
16+
import Cat.Reasoning as Cat
17+
18+
import Realisability.Data.Bool
19+
import Realisability.PCA.Sugar
20+
import Realisability.Base
1821
1922
open R hiding (def ; absurd)
2023
open Functor
@@ -71,6 +74,20 @@ $\tt{p}$ **realises** $x$. Moreover, for every $x : X$, we require that
7174
there be at least one $\tt{p}$ which realises it.
7275
:::
7376
77+
::: warning
78+
The construction of assemblies over $\bA$, and the category
79+
$\thecat{Asm}(\bA)$, works regardless of *which* pca $\bA$ we choose ---
80+
but we only get something *interesting* if $\bA$ is [[nontrivial|trivial
81+
pca]]: the category $\thecat{Asm}(*)$ over the trivial pca is the
82+
category $\Sets$.
83+
84+
Therefore, when making natural-language statements about
85+
$\thecat{Asm}(\bA)$, we generally assume that $\bA$ is nontrivial. A
86+
statement like "the category $\thecat{Asm}(\bA)$ is not
87+
[[univalent|univalent category]]" should be read as saying "univalence
88+
of $\thecat{Asm}(\bA)$ implies $\bA$ is trivial."
89+
:::
90+
7491
A prototypical example is the assembly of booleans, `𝟚`{.Agda}, defined
7592
[below](#the-assembly-of-booleans). Its set of elements is
7693
`Bool`{.Agda}, and we fix realisers
@@ -80,11 +97,11 @@ $$
8097
\left(\langle x \rangle \langle y \rangle\ y\right) \Vdash&\ \rm{false;}
8198
\end{align*}
8299
$$
83-
see [[pairs in a PCA]] for the details of the construction. This is not
100+
see [[booleans in a pca]] for the details of the construction. This is not
84101
the only possible choice: we could, for example, invert the realisers,
85102
and say that the value `true`{.Agda} is implemented by the *program*
86103
$\tt{false}$ (and vice-versa). This results in a genuinely different
87-
assembly, though with the same denotational data.
104+
assembly over `Bool`{.Agda}, though with the same denotational data.
88105
89106
```agda
90107
record Assembly (𝔸 : PCA ℓA) ℓ : Type (lsuc ℓ ⊔ ℓA) where
@@ -117,14 +134,17 @@ instance
117134
{-# CATCHALL #-}
118135
hlevel-proj-asm .hlevel-projection.get-argument _ = typeError []
119136
120-
module _ (X : Assembly 𝔸 ℓ) (a : ↯ ⌞ 𝔸 ⌟) (x : ⌞ X ⌟) where open Ω (X .realisers x .mem a) renaming (∣_∣ to [_]_⊩_) public
137+
module _ (X : Assembly 𝔸 ℓ) (a : ↯ ⌞ 𝔸 ⌟) (x : ⌞ X ⌟) where
138+
open Ω (X .realisers x .mem a) renaming (∣_∣ to [_]_⊩_) public
121139
122140
-- This module can't be parametrised so this display form can fire
123141
-- (otherwise it gets closed over pattern variables that aren't solvable
124142
-- from looking at the expression, like the level and the PCA):
125143
{-# DISPLAY realisers X x .ℙ⁺.mem a = [ X ] a ⊩ x #-}
126144
127-
subst⊩ : {𝔸 : PCA ℓA} (X : Assembly 𝔸 ℓ) {x : ⌞ X ⌟} {p q : ↯ ⌞ 𝔸 ⌟} → [ X ] p ⊩ x → q ≡ p → [ X ] q ⊩ x
145+
subst⊩
146+
: {𝔸 : PCA ℓA} (X : Assembly 𝔸 ℓ) {x : ⌞ X ⌟} {p q : ↯ ⌞ 𝔸 ⌟}
147+
→ [ X ] p ⊩ x → q ≡ p → [ X ] q ⊩ x
128148
subst⊩ X {x} hx p = subst (_∈ X .realisers x) (sym p) hx
129149
```
130150
-->
@@ -134,13 +154,22 @@ assembly of booleans and the swapped booleans, we define a morphism of
134154
assemblies $(X, \Vdash_X) \to (Y, \Vdash_Y)$ to be a function $f : X \to
135155
Y$ satisfying the [[*property*|propositional truncation]] that there
136156
exists a program $\tt{f} : \bA$ which sends realisers of $x : X$ to
137-
realisers of $f(x) : Y$. Note the force of the propositional truncation
138-
in this definition: maps of assemblies are identical *when they have the
139-
same underlying function*, regardless of what program implements them.
157+
realisers of $f(x) : Y$.
158+
159+
Note the force of the propositional truncation in this definition: maps
160+
of assemblies are identical *when they have the same underlying
161+
function*, regardless of which programs potentially implement them.
162+
Since we can not, for a general $\bA$, show that the programs
163+
$\mathtt{f}$ and
164+
$$
165+
\langle a \rangle\ f\ a
166+
$$
167+
are identical, $\thecat{Asm}(\bA)$ would not be a category if the choice
168+
of realiser mattered for identity of computable maps.
140169
141170
```agda
142171
record Assembly-hom {𝔸 : PCA ℓA} (X : Assembly 𝔸 ℓ) (Y : Assembly 𝔸 ℓ') : Type (ℓA ⊔ ℓ ⊔ ℓ') where
143-
open Logic 𝔸 using ([_]_⊢_)
172+
open Realisability.Base 𝔸 using ([_]_⊢_)
144173
145174
field
146175
map : ⌞ X ⌟ → ⌞ Y ⌟
@@ -155,7 +184,9 @@ instance
155184
H-Level-Assembly-hom : ∀ {n} → H-Level (Assembly-hom X Y) (2 + n)
156185
H-Level-Assembly-hom = basic-instance 2 $ Iso→is-hlevel 2 eqv (hlevel 2)
157186
158-
Extensional-Assembly-hom : ∀ {ℓr} ⦃ _ : Extensional (⌞ X ⌟ → ⌞ Y ⌟) ℓr ⦄ → Extensional (Assembly-hom X Y) ℓr
187+
Extensional-Assembly-hom
188+
: ∀ {ℓr} ⦃ _ : Extensional (⌞ X ⌟ → ⌞ Y ⌟) ℓr ⦄
189+
→ Extensional (Assembly-hom X Y) ℓr
159190
Extensional-Assembly-hom ⦃ e ⦄ = injection→extensional! (λ p → Iso.injective eqv (Σ-prop-path! p)) e
160191
161192
Funlike-Assembly-hom : Funlike (Assembly-hom X Y) ⌞ X ⌟ λ _ → ⌞ Y ⌟
@@ -168,11 +199,11 @@ instance
168199
-- all visible arguments to work with `record where` syntax.
169200
170201
record make-assembly-hom {𝔸 : PCA ℓA} (X : Assembly 𝔸 ℓ) (Y : Assembly 𝔸 ℓ') : Type (ℓA ⊔ ℓ ⊔ ℓ') where
171-
open PCA 𝔸 using (_%_)
202+
open Realisability.PCA.Sugar 𝔸 using (__)
172203
field
173204
map : ⌞ X ⌟ → ⌞ Y ⌟
174205
realiser : ↯⁺ 𝔸
175-
tracks : (x : ⌞ X ⌟) (a : ↯ ⌞ 𝔸 ⌟) (ah : [ X ] a ⊩ x) → [ Y ] realiser .fst % a ⊩ map x
206+
tracks : (x : ⌞ X ⌟) (a : ↯ ⌞ 𝔸 ⌟) (ah : [ X ] a ⊩ x) → [ Y ] realiser a ⊩ map x
176207
177208
open Assembly-hom public
178209
@@ -185,17 +216,17 @@ to-assembly-hom
185216
to-assembly-hom f = record { make-assembly-hom f using (map) ; tracked = inc record { make-assembly-hom f } }
186217
187218
module _ (𝔸 : PCA ℓA) where
188-
open Logic 𝔸
189-
open Sugar 𝔸
190-
open Pair 𝔸
219+
open Realisability.Base 𝔸
220+
open Realisability.PCA.Sugar 𝔸
221+
open Realisability.Data.Bool 𝔸
191222
192223
open Assembly-hom
193224
open Precategory
194225
```
195226
-->
196227
197228
This consideration is necessary for assemblies and assembly morphisms to
198-
be a category: in an arbitrary PCA $\bA$, composition of programs need
229+
be a category: in an arbitrary pca $\bA$, composition of programs need
199230
not be unital or associative.
200231
201232
```agda
@@ -214,7 +245,74 @@ not be unital or associative.
214245
Assemblies ℓ .assoc f g h = ext λ _ → refl
215246
```
216247
217-
## Classical assemblies
248+
::: warning
249+
Unlike most other categories constructed on the 1Lab, the category of
250+
assemblies is not [[univalent|univalent category]]. This is essentially
251+
*because* of the existence of assemblies such as `𝟚`{.Agda} and its
252+
"flipped" counterpart, described above: the identity map is a computable
253+
isomorphism between them, realised by the `` `not ``{.Agda} program, but
254+
there is no path in `Assembly`{.Agda} between them with first component
255+
projecting to the identity map.
256+
:::
257+
258+
However, these two assemblies *are* still identical in the type
259+
`Assembly`{.Agda}, where we allow the identification between the sets to
260+
be nontrivial --- their realisability relations are identical over the
261+
`not`{.Agda} equivalence --- hence the comment above about these being
262+
non-trivial assemblies "over bool".
263+
264+
<!--
265+
```agda
266+
_ = not
267+
_ = `not
268+
```
269+
-->
270+
271+
## The assembly of booleans
272+
273+
The assembly of booleans, $\tt{2}$, is the simplest example of an
274+
assembly which contains actual computability data. Its construction is
275+
entirely straightforward:
276+
277+
```agda
278+
𝟚 : Assembly 𝔸 lzero
279+
𝟚 .Ob = Bool
280+
𝟚 .has-is-set = hlevel 2
281+
𝟚 .realisers true = singleton⁺ `true
282+
𝟚 .realisers false = singleton⁺ `false
283+
𝟚 .realised true = inc (`true .fst , inc refl)
284+
𝟚 .realised false = inc (`false .fst , inc refl)
285+
```
286+
287+
We define the realisability relation as a function from `Bool`{.Agda},
288+
by cases: the only option for realising the boolean `true`{.Agda} is
289+
with the `` `true ``{.Agda} program, and similarly the `false`{.Agda}
290+
boolean is realised by the `` `false ``{.Agda} program. Both elements
291+
have those respective programs as their realisers.
292+
293+
## Indiscrete assemblies
294+
295+
However, the *assembly* of booleans is not the only assembly we can
296+
construct on the *type* of booleans. As mentioned above, we could also
297+
have inverted which program realises each boolean; but this is *still*
298+
an assembly with nontrivial computability data. Now, we show that the
299+
"ambient" world of sets and functions embeds [[fully faithful|fully
300+
faithful functor]] into the category of assemblies over any pca $\bA$.
301+
302+
This is, perhaps, a bit surprising: maps of assemblies are computable by
303+
definition, but arbitrary functions between sets need not be! The catch
304+
is that, when equipping a set with the structure of an assembly, *we*
305+
get to choose which programs compute each elements; and, above, we have
306+
made a sensible choice. But we can always make an *adversarial* choice,
307+
letting *every* program at all realise any element.
308+
309+
::: terminology
310+
We denote the **indiscrete assembly** on a set $X$ as $\nabla X$,
311+
following the literature. Note however that Bauer
312+
[-@Bauer:Realisability] refers to these as *constant assemblies*, while
313+
de Jong [-@deJong:Realisability] does not assign them a name but merely
314+
singles them out as embedding classical logic in $\thecat{Asm}(\bA)$.
315+
:::
218316
219317
```agda
220318
∇ : ∀ {ℓ} (X : Type ℓ) ⦃ _ : H-Level X 2 ⦄ → Assembly 𝔸 ℓ
@@ -225,7 +323,22 @@ not be unital or associative.
225323
; defined = λ x → x
226324
}
227325
∇ X .realised x = inc (expr ⟨ x ⟩ x , abs↓ _ _)
326+
```
327+
328+
The important thing to know about these is that any function of sets $X
329+
\to Y$ extends to a computable map of assemblies $(X, \Vdash) \to \nabla
330+
Y$ --- this is because the only requirement for $e \Vdash_{\nabla Y} f
331+
x$ is that $e$ is defined, and assemblies are defined so that if $e
332+
\Vdash_X x$ then $e$ is defined.
228333
334+
<details>
335+
<summary>Following the general logic of [[adjoint functors]], this means
336+
that $\nabla (-)$ is a functor $\Sets \to \thecat{Asm}(\bA)$, for any
337+
$\bA$ at all --- and moreover that $\nabla$ is a [[right adjoint]] to
338+
the functor $\Gamma : \thecat{Asm}(\bA) \to \Sets$ which projects the
339+
underlying set of each assembly.</summary>
340+
341+
```agda
229342
Cofree : Functor (Sets ℓ) (Assemblies ℓ)
230343
Cofree .F₀ X = ∇ ⌞ X ⌟
231344
Cofree .F₁ f = to-assembly-hom record where
@@ -254,29 +367,19 @@ not be unital or associative.
254367
Forget⊣∇ .zag = ext λ _ → refl
255368
```
256369
257-
## The assembly of booleans
370+
</details>
258371
259-
```agda
260-
𝟚 : Assembly 𝔸 lzero
261-
𝟚 .Ob = Bool
262-
𝟚 .has-is-set = hlevel 2
263-
𝟚 .realisers true = record
264-
{ mem = λ x → elΩ (`true .fst ≡ x)
265-
; defined = rec! λ p → subst ⌞_⌟ p (`true .snd)
266-
}
267-
𝟚 .realisers false = record
268-
{ mem = λ x → elΩ (`false .fst ≡ x)
269-
; defined = rec! λ p → subst ⌞_⌟ p (`false .snd)
270-
}
271-
𝟚 .realised true = inc (`true .fst , inc refl)
272-
𝟚 .realised false = inc (`false .fst , inc refl)
273-
```
372+
The indiscrete assemblies $\nabla X$ are generally poor as *domains* for
373+
computable functions, since a realiser for $f : \nabla X \to (Y,
374+
\Vdash)$ would have to choose realisers for $f(x)$ given no information
375+
about $x$. Indeed, we can show that if there are non-constant maps
376+
$\nabla \{0, 1\} \to \tt{2}$, then $\bA$ is [[trivial|trivial pca]].
274377
275378
```agda
276379
non-constant-nabla-map
277380
: (f : Assembly-hom (∇ Bool) 𝟚)
278381
→ f · true ≠ f · false
279-
`true .fst ≡ `false .fst
382+
is-trivial-pca 𝔸
280383
non-constant-nabla-map f x = case f .tracked of λ where
281384
record { realiser = (fp , f↓) ; tracks = t } →
282385
let
@@ -294,3 +397,9 @@ not be unital or associative.
294397
false false p → rec! λ rb rb' f≠f → absurd (f≠f refl)
295398
in cases (f · true) (f · false) _ a b x
296399
```
400+
401+
<!--
402+
```agda
403+
module Asm {ℓA ℓ} {𝔸 : PCA ℓA} = Cat (Assemblies 𝔸 ℓ)
404+
```
405+
-->

src/Data/Partial/Base.lagda.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,14 @@ part-ap f x .elt (pf , px) = f .elt pf (x .elt px)
210210
is-always : {A : Type ℓ} (a : ↯ A) (x : ⌞ a ⌟) → a ≡ always (a .elt x)
211211
is-always a x = part-ext (λ _ → tt) (λ z → x) λ _ _ → ↯-indep a
212212
213+
always-injective : {A : Type ℓ} {x y : A} → always x ≡ always y → x ≡ y
214+
always-injective p = ap₂ unalways p q where
215+
unalways : (x : ↯ A) → ⌞ x ⌟ → A
216+
unalways = elt
217+
218+
q : PathP (λ i → ⌞ p i ⌟) tt tt
219+
q = is-prop→pathp (λ i → p i .def .is-tr) tt tt
220+
213221
instance
214222
↯-Map : Map (eff ↯)
215223
↯-Map .Map.map = part-map

src/Data/Partial/Total.lagda.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,9 @@ from-total-predicate-is-equiv = is-iso→is-equiv λ where
109109
.rinv P → ext λ a → Ω-ua (rec! (λ ha → subst (_∈ P) (sym (is-always a ha)))) λ pa → P .defined pa , subst (_∈ P) (is-always a _) pa
110110
.linv P → ext λ a → Ω-ua snd (tt ,_)
111111
```
112+
113+
```agda
114+
singleton⁺ : ↯⁺ A → ℙ⁺ A
115+
singleton⁺ x .mem y = elΩ (x .fst ≡ y)
116+
singleton⁺ x .defined = rec! λ p → subst ⌞_⌟ p (x .snd)
117+
```

src/Realisability/Data/Bool.lagda.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!--
2+
```agda
3+
open import 1Lab.Prelude
4+
5+
open import Data.Partial.Total
6+
open import Data.Partial.Base
7+
open import Data.Vec.Base
8+
9+
open import Realisability.PCA
10+
11+
import Realisability.PCA.Sugar as S
12+
```
13+
-->
14+
15+
```agda
16+
module Realisability.Data.Bool {ℓ} (𝔸@(A , _) : PCA ℓ) where
17+
```
18+
19+
<!--
20+
```agda
21+
open S 𝔸
22+
private variable
23+
a b : ↯ ⌞ 𝔸 ⌟
24+
```
25+
-->
26+
27+
# Booleans in a PCA {defines="booleans-in-a-pca"}
28+
29+
```agda
30+
`true : ↯⁺ 𝔸
31+
`true = val ⟨ x ⟩ ⟨ y ⟩ x
32+
33+
`false : ↯⁺ 𝔸
34+
`false = val ⟨ x ⟩ ⟨ y ⟩ y
35+
36+
`not : ↯⁺ A
37+
`not = val ⟨ x ⟩ x `· `false `· `true
38+
39+
abstract
40+
`true↓₁ : ⌞ a ⌟ → ⌞ `true ⋆ a ⌟
41+
`true↓₁ x = subst ⌞_⌟ (sym (abs-βₙ [] ((_ , x) ∷ []))) (abs↓ _ _)
42+
43+
`false↓₁ : ⌞ a ⌟ → ⌞ `false .fst % a ⌟
44+
`false↓₁ ah = subst ⌞_⌟ (sym (abs-βₙ [] ((_ , ah) ∷ []))) (abs↓ _ _)
45+
46+
`false-β : ⌞ a ⌟ → ⌞ b ⌟ → `false ⋆ a ⋆ b ≡ b
47+
`false-β {a} {b} ah bh = abs-βₙ [] ((b , bh) ∷ (a , ah) ∷ [])
48+
49+
`true-β : ⌞ a ⌟ → ⌞ b ⌟ → `true ⋆ a ⋆ b ≡ a
50+
`true-β {a} {b} ah bh = abs-βₙ [] ((b , bh) ∷ (a , ah) ∷ [])
51+
52+
`not-βt : `not ⋆ `true ≡ `false .fst
53+
`not-βt = abs-β _ [] `true ∙ abs-βₙ [] (`true ∷ `false ∷ [])
54+
55+
`not-βf : `not ⋆ `false ≡ `true .fst
56+
`not-βf = abs-β _ [] `false ∙ abs-βₙ [] (`true ∷ `false ∷ [])
57+
```

src/Realisability/Data/Nat.lagda.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ open import Data.Vec.Base
99
open import Realisability.PCA
1010
1111
import Realisability.PCA.Fixpoint
12+
import Realisability.Data.Bool
1213
import Realisability.Data.Pair
1314
import Realisability.PCA.Sugar
1415
```
@@ -23,6 +24,7 @@ module Realisability.Data.Nat {ℓ} (𝔸 : PCA ℓ) where
2324
open Realisability.PCA.Fixpoint 𝔸
2425
open Realisability.PCA.Sugar 𝔸
2526
open Realisability.Data.Pair 𝔸
27+
open Realisability.Data.Bool 𝔸
2628
```
2729
-->
2830

0 commit comments

Comments
 (0)