On the other hand, GitLab Pages is much less restrictive with what’s allowed,
because the build process is literally just a
CI script.
This bypasses the plugins allowlist, but not the configuration overrides, which are from the `github-pages`

Gem.
The first thing to do, then, is to forego the Gem and include only the plugins I need in `Gemfile`

.
On top of that, I have the Gems required to use KaTeX as kramdown’s math engine.

```
source "https://rubygems.org"
gem "jekyll-feed"
gem "jekyll-gist"
gem "jekyll-paginate"
gem "jekyll-remote-theme"
gem "katex"
gem "kramdown-math-katex"
```

`github-pages`

also specifies a number of default configurations,
but most of these are either Jekyll defaults
or undesirable (namely allowlist plugins and kramdown configurations).
I also already have a number of configurations set from when I was using GH Pages.
The below are the only missing configurations that needed adding in `_config.yml`

to include the Jekyll plugins and to enable using KaTeX for kramdown.

```
plugins:
- jekyll-feed
- jekyll-gist
- jekyll-paginate
- jekyll-remote-theme
kramdown:
math_engine: katex
```

Finally, to use GitLab Pages, there needs to be a CI configuration script to install Node.js
(since `kramdown-math-katex`

needs to run KaTeX) and to build the Jekyll site.

```
image: ruby:latest
pages:
script:
- apt-get update && apt-get -y install nodejs
- gem install bundler
- bundle install
- bundle exec jekyll build -d public
artifacts:
paths:
- public
```

Now inline LaTeX works everywhere using double dollar signs:
`$$\displaystyle \int_{\partial \Omega} \omega = \int_{\Omega} d\omega$$`

yields
$\int_{\partial \Omega} \omega = \int_{\Omega} d\omega$.
There aren’t any delimiters for display-style math,
but you can always add `\displaystyle`

to a block of LaTeX.

Known as right angle with downwards zigzag arrow,
angle with down zig-zag arrow,
`\rangledownzigzagarrow`

,
and `⍼`

,
no one knows what ⍼ is meant to represent or where it originated from.
Section 22.7 Technical Symbols
from the Unicode Standard on the
Miscellaneous Technical block
doesn’t say anything about it.

The original proposal that included this character is Proposal for Encoding Additional Mathematical Symbols in the BMP (N2191) from 14 March 2000, with origins from the STIX project. That project page links to a number of relevant files dating all the way back to 1997, and most importantly to the very first collation of character tables by Barbara Beeton last updated on 24 June 1997. Here we find that, in table &ac-&cirmid under codes with TR 9573 names, an entry for the character.

AFIIISO TR9573 entityISO TR9573 descriptionD97C ⍼ angle with down zig-zag arrow

(This table is later merged into a larger table.) A table from 18 July 1997 clarifies that these are characters from the technical report TR 9573-13. A later table from 7 Feburary 1998 with accompanying glyphs confirms that this is indeed the character we’re looking for.

UnicodeGlyphSGMLNameDescriptionE248 angzarr ISOAMSA angle with down zig-zag arrow

The Unicode code point E248 is, of course, not its current actual code point. That one is located in a Private Use Area (PUA) in the Basic Multilingual Plane (BMP), and so was likely a temporary encoding within STIX before acceptance into Unicode proper. The AFII code point D97C will be explained later, as will what AFII stands for and what it is.

Related is the Mathematical Markup Language (MathML) Specification: Section 6.2.5.1 ISO Symbol Entity Sets provides the same tables as STIX, and our character can again be found in group ISO AMS-A.

The technical report, whose long name is
ISO/IEC TR 9573-13:1991 Techniques for using SGML — Part 13: Public entity sets for mathematics and science,
was published in July 1991.
Although their site claims there was never a newer version,
there is a document with the same name
last updated on 8 December 2003.
It indeed lists U+237C in Section 7.1 isoamsa,
but evidently this came *after* it was added to the Unicode Standard.

The actual tech report itself doesn’t provide much more information than the newer document,
shown in the capture above:
all it contains is its short name, the glyph, its old code point D97C, and a description.
(If you’re a UBC student or faculty, you can get access to the
tech report via Techstreet
or here.)
The only other reference is found in Section 6.2.5 Arrow Relations,
which gives the same entity listings as
ISOasma.ent
in the Debian package `sgml-data`

.

The Foreword of the tech report, though, mentions that it replaces an earlier annex.

h) Part 13 replaces ISO 8879:1986 annex D (in part)

Taking a look at ISO/IEC TR 9573:1988 Techniques for using SGML as well, which people at UBC can also access via CSA onDemand as CAN/CSA-Z243.210.1-89 (R2018), it also indicates that the symbols it uses comes from ISO 8879.

However, this Annex D of ISO 8879:1986 Standard Generalized Markup Language (SGML) (which UBC people can again access as CAN/CSA-Z243.210-89 (R2014) via CSA onDemand or here) doesn’t contain our character, neither under ISO AMS-A as expected, nor anywhere else. This does explain the category name, at least: “AMS” here stands for “Added Math Symbols”, and has nothing to do with the American Mathematical Society.

Annex D.4.4 Technical Use has a brief note on the origin of the names of the entities it *does* list, though.

NOTE — Visual depictions of most of the technical use entities are identified by their entity names in Association of American Publishers Electronic Manuscript Series: Markup of Mathematical Formulas, published by the Association of American Publishers, Inc., 2005 Massachusetts Avenue, N.W., Washington, DC 20036, U.S.A.

I obtained a second edition copy of *Markup of Mathematical Formulas*
from the University of Victoria, which lists the same entities, also missing our character.

Back in TR 9573-13, Section 5 mentions that the symbols tables contain

a glyph identifier, registered in accordance with ISO/IEC 10036. The glyph identifier is shown in decimal and hexadecimal representation;

this refers to the code point D97C/55676. While ISO/IEC 10036:1993 Procedure for registration of glyph and glyph collection identifiers (accessible as CAN/CSA-ISO/IEC 10036-01 (R2014)) only describes glyph registration, the actual 10036 registry exists online. Our character can be found among code points 556xx. In 2020, the glyph table was standardized as ISO/IEC TR 10036:2020 Registered glyph identifiers, containing the same glyphs.

55676

The registry indicates that this glyph is among thousands inherited from the Association for Font Information Interchange (AFII), established in 1987 (according to this search). They had their own registry as well, cited by ISO/IEC 10036:1996, Annex D Bibliography.

Association for Font Information Interchange (AFII)

International Glyph Register, Volume 1: Alphabetic Scripts and Symbols. 1993.

The AFII is long dissolved in favour of Unicode over their glyph registry; an email from Asmus Freytag, their former president, describes its history just before dissolution. Notably, it appears that anyone could register a glyph with the AFII for a fee of 5$ to 50$ (about 8.60$ to 86$, accounting for inflation). ISO/IEC 10036 provides the registration process along with contact information for the AFII in Annex A Registration Authority.

Association for Font Information Interchange

Post Office Box 33683

Northglenn, Colorado 80233-0683

Telephone: +1 303 924-7670

Facismile: +1 303 451-5475

Email: afii@ix.netcom.com

Even if the *International Glyph Register* can be found,
it likely merely contains another table with the glyph, the indentifier, and the short description.
To know its origins would require the original registration request that added the character,
but it’s unlikely that such old documents from a now-defunct non-profit organization in the 90s
would have been kept or digitized.

After asking on the TeX Stack Exchange about the origin and meaning of the character, Barbara Beeton herself gave a response.

I had no idea what it meant or was used for, thus assigned it a “descriptive name” when collating the symbols for the STIX project. (I still have no idea, nor can supply an example of the symbol in use.) […] it is the case that ISO 9573-13 existed long before either AFII or the STIX project were formed. […] I once asked Charles Goldfarb what the source of these entities was, but remember that he didn’t have a definitive answer.

So its appearance in AFII’s registry comes *after* TR 9573-13,
which explains the fact that the registry was published in 1993 while the tech report in 1991,
although the tech report does reference ISO/IEC 10036,
whose earliest version was apparently published in 1993.
It’s possible there were earlier, unpublished versions of these documents.

In a follow-up comment, Beeton says:

Although I did ask, no one was able to tell me whether there was a single source or the entities were just picked up from a number of sources.

And in reference to Half as Interesting’s video:

The information in the video is inaccurate. It fails to recognize that the inclusion of the character in the STIX collection was based on its presence in a version of ISO 9573-13 earlier than the 1991 version cited, a version which existed long before AFII was formed. So any claim that it originated with AFII is chronologically invalid.

If she was unable to find a source while actively working with AFII and STIX back in the 90s, I doubt I would be able to uncover anything new now, three decades later. Here, then, I close the book on my investigation. The meaning of ⍼ will be whatever meaning is assigned by whoever uses it next… if anyone uses it at all.

- 1983: AAP Electronic Manuscript Project
begins, publishing a series that includes
*Markup of Mathematical Formulas* - 1986-10-15: ISO 8879 (SGML) is published,
containing ISO AMS-A without ⍼, referencing
*Markup of Mathematical Formulas* - 1987-09-15: AFII is established
- 1987-11:
*Markup of Mathematical Formulas*, 2 ed. is published without ⍼, referencing ISO 8879 - 1988-12: ISO/IEC TR 9573 (Techniques for using SGML) is published, referring to ISO 8879
- 1988: ISO 8879 is revised with a new Annex J
- 1988: ANSI/NISO Z39.59 (AAP Electronic Manuscript Standard) is published, based on part of the published series, likely with no entity tables
- 1991-07-01: ISO/IEC TR 9573-13 (Public entity sets for mathematics and science) is published, containing ISO AMS-A with the first verifiable occurrence of ⍼, referencing ISO/IEC 10036
- 1993-06: ISO/IEC 10036 (Glyph registration) is published
- 1993:
*International Glyph Register*by the AFII is published, possibly containing ⍼ - 1994-09: ISO 12083 (Electronic manuscript preparation and markup) is published, based on ANSI/NISO Z39.59, with no entity tables
- 1996-07: ISO/IEC 10036 is revised,
referencing the
*International Glyph Register* - 1997-06: The STIX project begins, taking character tables from ISO/IEC TR 9573-13
- 2000-03-14: ISO/IEC JTC1/SC2/WG2 N2191 (Proposal for Encoding Additional Mathematical Symbols) is proposed, adding ⍼ to the Unicode Standard

What is the glyph *supposed* to look like?
Obviously without a definitive source, we can’t answer this question,
but we can look at what various interpretations of a downwards zig-zag arrow
overtop a right angle exist, starting with a vector reproduction of the glyph in the 10036 registry,
originally a 96 px × 96 px GIF and supposedly copied from AFII’s registry.

The zig-zag in question has a horizontal middle bar, with the lower bar crossing the corner of the angle. Then we have the glyph from TR 9573-13, which is luckily available as a proper PDF with vector glyphs rather than a scanned document.

The zig-zag in question also contains a horizontal middle bar, but the lower bar doesn’t cross the angle corner. The arrowhead has a rather unusual shape, but is in line with the arrowheads of the other glyphs. Strangely, the vertical bar of the right angle doesn’t have a consistent width. Next is a vector reproduction of the glyph from both STIX and MathML, which were originally 32 px × 32 px GIFs.

For some reason, the middle bar of the zig-zag is now diagonal rather than horizontal. There’s also an extra pixel at the bottom bend, and the arrow now crosses the corner of the right angle. Fun fact: the horizontal bar of the right angle is a single pixel shorter than the vertical bar. Then we have the glyph as designed in the Unicode proposal document.

This one just looks like a vectorized version of the previous pixellated version. I don’t think the pixellated glyph is a downsampled version of this glyph, since the arrowhead in this glyph is larger and extends beyond the angle corner.

These last four are examples of the character in four different fonts that provide it: GNU Unifont, STIX Two, Julia Mono, and Noto Sans Math/Noto Sans Symbols. Unifont’s glyph looks like an improved version of the pixellated version: the extra pixel is gone, both bends are the same size around the vertical bar, and the arrowhead is slightly larger and more distinguishable. STIX Two’s resembles the proposal version but with a fancier arrowhead. Julia Mono’s is a little weird: the bottommost bar of the zig-zag isn’t straight, and the vertical bar of the angle again has inconsistent widths (although an issue’s been opened for that). Finally, Noto Sans’ glyph doesn’t even have a zig-zag; They’ve chosen to interpret the character as a wavy arrow rather than a zig-zag arrow. All of these have an arrow crossing the right angle corner, which seems to be a distinguishing characteristic of the character.

*What is ⍼ used for?*on TeX SE and Math SE- Twitter thread about this post
- Ellis (), a chaos magic sigil that looks suspiciously similar to ⍼
*The Assault on Reality*, the origin of Ellis (referred to as the Linking Sigil)- Hacker News, Lobste.rs, and Hackaday discussions
- XKCD #2606 mentions ⍼ and its Explain XKCD entry cites this post
- Half as Interesting did a video on this post (don’t bother, it’s less than half as interesting)

```
⎾⎿⏀⏁⏂⏃⏄⏅⏆⏇⏈⏉⏊⏋⏌
```

The first two and last two are part of Palmer notation for denoting human teeth by their position. What are the rest for?

The Unicode Standard, Section 22.7 Technical Symbols, doesn’t have much specific to say about the matter.

Dental Symbols.The set of symbols from U+23BE to U+23CC form a set of symbols from JIS X 0213 for use in dental notation.

Looking at the Miscellaneous Technical code chart, their names describe the appearance of the symbols but not so much their function.

```
23C0 ⏀ DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE
23C1 ⏁ DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE
23C2 ⏂ DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE
23C3 ⏃ DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE
23C4 ⏄ DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE
23C5 ⏅ DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE
23C6 ⏆ DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE
23C7 ⏇ DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE
23C8 ⏈ DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE
23C9 ⏉ DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL
23CA ⏊ DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL
```

The JIS X 0213 is yet another character set encoding standard and doesn’t explain much either. Any technical documents would probably be in Japanese, which I can’t read. Luckily, the Wikipedia page on Miscellaneous Technical keeps a pretty extensive historical record of how its characters were introduced into Unicode. According to the table, the dentistry symbols were introduced in version 3.2 originating from a proposal in 1999. Here’s where we’ll start our hunt for their meaning.

The dentistry symbols along with some circled digits were introduced in Addition of medical symbols and enclosed numbers on 13 September 1999. The document doesn’t actually explain what the symbols mean.

The Unicode Technical Committee has the same questions I do. The meeting minutes for a committee meeting over 26–29 October 1999 note:

Twenty Seven Dentist Characters

Consensus 81-C5: The circled characters will considered as part of a general mechanism as documented in 81-C4. Respond to the Shibano-san on the remaining proposed dentist symbols that we need evidence of usage. The UTC is not accepting any of the dentist symbols at this time. [L2/99-238]

Action Item 81-33 for Lisa Moore: Inform Shibano-san that we are not accepting any of the dentist symbol characters, and provide our feedback.

And so in a proposal comment on 23 November 1999, Lisa Moore, chair of the Committee, writes:

6) Twenty Seven Dentist Characters. The UTC will consider the ten double circled numbers as part of the general mechanism to be defined in the future. See 4) above. The remaining seventeen dentist symbols were not accepted due to insufficient evidence of usage. Please provide documents with examples of usage, and explain if any of these characters are combining, or if any extend across other symbols to delineate quadrants of the jaw.

The 17 symbols refer to the 15 dentistry symbols along with U+29FA ⧺ double plus and U+29FB ⧻ triple plus, which are later encoded in Miscellaneous Mathematical Symbols-B. In a proposal revision on 31 January 2000, Professor Kohji Shibano, chairman of the JCS committee, writes:

(c) Evidence of usage

You requested to submit evidence of usage for some characters. We are now preparing the requested document for the following characters with some explanation in English. This document will be sent to you as soon as possible.

Finally, in Rationale for non-Kanji characters proposed by JCS committee on 15 March 2000, the dentistry symbols are… “explained”.

(2) Dentist’s symbols

These symbols are used in dentistry when drawing XXX together with some BOX DRAWING characters. The proposal includes two types of characters; those used in single-line drawing and those in triple-line drawing.

It makes sense that the lines are meant to be used with box-drawing characters in dental notation to illustrate the teeth. But what do the circle, the triangle, and the tilde mean? The Wikipedia article on dental notation doesn’t seem to use these symbols (and nor does the corresponding German article, which is much more comprehensive).

The committees, on the other hand, seem satisfied with this explanation. The meeting minutes for an ISO/IEC subcommittee meeting over 21–24 March 2000 note a comment (Section 8.20, page 44) by Dr. Ken Whistler of Sybase, Inc.:

ii) The Dental symbols are sufficiently explained - these are box-drawing characters overlaid in specific manner.

The meeting minutes for a Unicode Technical Committee meeting on 28 April 2000 read:

[83-M3] Motion: Accept the twenty five characters documented in the report on the Beijing meeting, sections E 1, 2, 3, 5, 6, 7, 8, 9 [L2/00-108]:

⚬ Double plus sign and triple plus sign

⚬ 15 dentist symbols

So there aren’t any more explanations we can expect to see from these documents. Subsequent meeting minutes only discuss technical details. From 19–22 September 2000 (Section 7.21, page 40):

Action Items: Messrs. Michael Everson and Takayuki Sato - will provide better glyphs for the DENTIST Symbols (from document N2093). The amendment text is to be prepared by the editor.

From 9 March 2001 (Irish comments, page 5):

Table 63 (67) - Row 23: Miscellaneous Technical

The Japanese remarked in Athens that the glyphs for the dentistry symbols 23C0-23CC should fill a notional square. We have provided the editor with corrected glyphs.

And from 2–5 April 2001, more remarks on the shape of the characters (Section 7.1, page 21), and the proposed character names are changed from DENTIST to DENTISTRY (Section 7.1, page 22):

Comment 14: Shapes of JIS X0213 characters – Accepted.

Japan will supply suitable fonts. Kana has to cover all existing Kana characters also. As to the Dentist symbols, glyphs do not seem to look square. We need to know why current glyphs are not acceptable. A single font is needed for a range.

SE6: […] Rename DENTIST to DENTISTRY symbols … should it be DENTAL? Accept DENTISTRY.

On 27 March 2002, Unicode 3.2 is released. The current blurb on dentistry symbols is added as part of the Unicode Standard Annex #28; the new code points are highlighted in this code chart.

I don’t have any dentistry friends, but surely someone knows, so I asked around. I asked the Medical Sciences Stack Exchange, I asked on the Unicode mailing list, and I even threw the question out there on Twitter. In the end, though, someone I knew found it with a method so simple it never occurred to me.

And indeed, an explanation can be found right there in Dental Computing and Applications: Advanced Techniques for Clinical Dentistry by Andriani Daskalaki, published in 2009. In fact, a simple “dentistry unicode” search on Google Books takes me right there.

Of course, this isn’t the *origin* of the symbols, but it does explain what they mean.
According to Chapter XVII on
Unicode Characters for Human Dentition^{†},
the notation comes from Japan’s dental insurance claim system.

Although these signs are not specific to dentistry, we assigned a specific meaning to these modified numerical symbols in accordance with the dental insurance claim system in Japan.

…

Figure 4 shows nine characters in three groups denoting artificial teeth, supernumerary teeth and an abbreviation for a group of teeth respectively. A triangle with a bar indicates an artificial spacer, especially on a denture, a circle with a bar indicates a supernumerary tooth, and a tilde with a bar indicates an abbreviation for a group of teeth.

So that’s the end of the mystery. I should go update all the places I’ve asked with this discovery now.

Since the original publication of this post I’ve received some replies to my question posted to the Unicode mailing list, in particular Ryusei Yamaguchi’s response. Some of the sources cited agree with the above: 歯式の記載について on dental notation lists using ⏈ for describing a span of upper teeth and ⏇ for describing a span of lower teeth.

⏈: この記号の両端の歯の間に存在する全ての歯（上顎用で正中を越える）

[DeepL translation: “All teeth present between the teeth on either side of this sign (for maxillary and beyond the median)”]

⏇: この記号の両端の歯の間に存在する全ての歯（下顎用で正中を越える）

[DeepL translation: “All teeth present between the teeth on either side of this sign (for mandible and beyond the midline)”]

On the other hand, 電子レセプトの作成手引き on filing electronic dental insurance claims uses △ to indicate 「部近心隙」 (page 25), which seems to mean a diastema, or a tooth gap, so that ⏅⏃⏄ are used to indicate a gap between the front teeth, rather than artificial teeth as previously suggested. This usage is further backed up by the 歯式メーカー app, which describes using △ to indicate a gap.

△で隙を入力します。選択した歯の近心の隙を入力します。

[Google Translate: “Enter the gap with △. Enter the mesial gap of the selected tooth.”]

Finally, there doesn’t seem to be any other explanation of the circle and the usage of ⏂⏀⏁. Circled numbers indicate dental implants at the given tooth position, so it doesn’t make sense in that case for the circle to go in between teeth. It’s likely, then, that they are indeed for indicating supernumary teeth, and in particular the mesiodentes that occur between the two front teeth.

^{†}This does require access to IGI Global’s resources,
but you can just find the entire book here.

- Well-Founded Trees
- Indexed Well-Founded Trees
- Indexed Inductives and Fording
- Nested Inductives
- Inductive–Inductives
- Inductive–Recursives
- Indexed Well-Founded Trees as Canonized Well-Founded Trees

```
data W (A : 𝒰) (B : A → 𝒰) : 𝒰 where
sup : ∀ a → (B a → W A B) → W A B
```

`A`

selects the constructor as well as providing the constructor’s nonrecursive arguments.
`B`

then selects the recursive element as well as providing the recursive element’s arguments.

```
data Ord (A : 𝒰) : 𝒰 where
Z : A → Ord A
S : Ord A → Ord A
L : (ℕ → Ord A) → Ord A
Ord A = W (A + 𝟙 + 𝟙) B
where
B (in1 a) = 𝟘
B (in2 ∗) = 𝟙
B (in3 ∗) = ℕ
Z a = sup (in1 a) absurd
S o = sup (in2 ∗) (λ _ → o)
L f = sup (in3 ∗) f
```

```
data IW (I : 𝒰)
(A : I → 𝒰)
(B : ∀ i → A i → 𝒰)
(d : ∀ i → (a : A i) → B i a → I) :
I → 𝒰 where
isup : ∀ i → (a : A i) →
((b : B i a) → IW I A B d (d i a b)) →
IW I A B d i
```

The indexed W type can be seen as either encoding an inductive type with nonuniform parameters
or as encoding mutual inductive types, which are indexed inductive types anyway.
`I`

selects the nonuniform parameters, which I’ll call the index for now
`A`

selects the constructor, `B`

selects the recursive element,
and `d`

returns the index of that recursive element.

```
data Even : 𝒰 where
Z : Even
Sₑ : Odd → Even
data Odd : 𝒰 where
Sₒ : Even → Odd
EvenOdd = IW 𝟚 A B d
where
Even = in1 ∗
Odd = in2 ∗
A Even = 𝟚 -- Even has two constructors
A Odd = 𝟙 -- Odd has one constructor
B Even (in1 ∗) = 𝟘 -- Z has no recursive elements
B Even (in2 ∗) = 𝟙 -- Sₑ has one recursive element
B Odd ∗ = 𝟙 -- Sₒ has one recursive element
d Even (in1 ∗) = absurd
d Even (in2 ∗) ∗ = Odd
d Odd ∗ ∗ = Even
Z = isup Even (in1 ∗) absurd
Sₑ o = isup Even (in2 ∗) (λ _ → o)
Sₒ e = isup Odd ∗ (λ _ → e)
```

```
variable
T : 𝒰
_<_ : T → T → 𝒰
data Acc (t : T) : 𝒰 where
acc : (∀ s → s < t → Acc s) → Acc t
Acc t = IW T (λ _ → 𝟙) (λ t ∗ → ∃[ s ] s < t) (λ t ∗ (s , _) → s) t
```

```
data PTree (A : 𝒰) : 𝒰 where
leaf : A → PTree A
node : PTree (A × A) → PTree A
PTree = IW 𝒰 (λ A → A + 𝟙) B d
where
B A (in1 a) = 𝟘
B A (in2 ∗) = 𝟙
d A (in1 a) = absurd
d A (in2 ∗) ∗ = A × A
leaf A a = isup A (in1 a) absurd
node A t = isup A (in2 ∗) (λ _ → t)
```

So far, (nonuniformly) parametrized inductives and mutual inductives can be encoded. Indexed inductives can be encoded as well by first going through a round of fording to turn them into nonuniformly parametrized inductives. Meanwhile, mutual inductives can also be represented as nonuniform parametrized inductives by first turning them into indexed inductives.

```
variable
A B : 𝒰
data Image (f : A → B) : B → 𝒰 where
image : ∀ x → Image f (f x)
-- Forded image type
data Image' (f : A → B) (b : B) : 𝒰 where
image' : ∀ x → b ≡ f x → Image f b
Image' f b = W (∃[ x ] b ≡ f x) 𝟘
image' x p = sup (x , p) absurd
```

```
data Fin : ℕ → 𝒰 where
FZ : ∀ n → Fin (S n)
FS : ∀ n → Fin n → Fin (S n)
-- Forded finite sets type
data Fin' (m : ℕ) : 𝒰 where
FZ' : ∀ n → m ≡ S n → Fin m
FS' : ∀ n → m ≡ S n → Fin n → Fin m
Fin' = IW ℕ (λ m → 𝟚 × ∃[ n ] m ≡ S n) B d
where
B m (in1 ∗ , n , p) = 𝟘
B m (in2 ∗ , n , p) = 𝟙
d m (in1 ∗ , n , p) = absurd
d m (in2 ∗ , n , p) ∗ = n
FZ' m n p = isup m (in1 ∗ , n , p) absurd
FS' m n p fin = isup m (in2 ∗ , n , p) (λ _ → fin)
```

Nested inductive types, when represented as recursive μ types, have nested type binders. Nonindexed inductive types potentially with nonuniform parameters, on the other hand, are single μ types.

```
Ord A = μX: 𝒰. A + X + (ℕ → X)
EvenOdd = μX: 𝟚 → 𝒰. λ { in1 ∗ → 𝟙 + X (in2 ∗) ; in2 ∗ → X (in1 ∗) }
Acc = μX: T → 𝒰. λ t → ∀ s → s < t → X s
PTree = μX: 𝒰 → 𝒰. λ A → A + X (A × A)
Fin' m = μX: ℕ → 𝒰. (∃[ n ] m ≡ S n) + (∃[ n ] (m ≡ S n) × X n)
```

Nested inductives, when not nested within themselves, can be defunctionalized into indexed inductives, which can then be forded into nonuniformly parametrized inductives, which can finally be encoded as indexed W types.

```
data FTree : 𝒰 where
ftree : List FTree → FTree
FTree = μX: 𝒰. List X = μX: 𝒰. μY: 𝒰. 𝟙 + X × Y
data I : 𝒰 where
Tree : I
List : I → I
data Eval : I → 𝒰 where
nil : Eval (List Tree)
cons : Eval Tree → Eval (List Tree) → Eval (List Tree)
ftree : Eval (List Tree) → Eval Tree
data Eval' (i : I) : 𝒰 where
nil' : i ≡ List Tree → Eval' i
cons' : i ≡ List Tree → Eval' Tree → Eval' (List Tree) → Eval' i
ftree : i ≡ Tree → Eval' (List Tree) → Eval' i
Eval' = IW I A B d
where
A i = i ≡ List Tree + i ≡ List Tree + i ≡ Tree
B _ (in1 _) = 𝟘
B _ (in2 _) = 𝟚
B _ (in3 _) = 𝟙
d _ (in1 _) = absurd
d _ (in2 _) (in1 ∗) = Tree
d _ (in2 _) (in2 ∗) = List Tree
d _ (in3 _) ∗ = List Tree
```

It’s unclear how this might be encoded either as indexed inductives or as an indexed W type.

```
data Bush (A : 𝒰) : 𝒰 where
bnil : Bush A
bcons : A → Bush (Bush A) → Bush A
Bush = μX: 𝒰 → 𝒰. λ A → 𝟙 + A × X (X A)
```

While mutual inductives allow the types of constructors of multiple inductives to refer to one another, inductive–inductives further allow one inductive to be a parameter or index of another.

```
data A : 𝒰 where
…
data B : A → 𝒰 where
…
```

That is, the entries of a context must be well formed under the correct context, while the context under which types are well formed must themselves be well formed.

```
data Ctxt : 𝒰 where
· : Ctxt
_∷_ : ∀ Γ → Type Γ → Ctxt
data Type : Ctxt → 𝒰 where
U : ∀ Γ → Type Γ
Var : ∀ Γ → Type (Γ ∷ U Γ)
Pi : ∀ Γ → (A : Type Γ) → Type (Γ ∷ A) → Type Γ
```

To encode this inductive–inductive type, it’s split into two mutual inductives:
an “erased” one with the type interdependency removed (i.e. `Type'`

does not have a `Ctxt'`

parameter),
and one describing the relationship between the two.

```
data Ctxt' : 𝒰 where
· : Ctxt'
_∷_ : Ctxt → Type → Ctxt
data Type' : 𝒰 where
U : Ctxt' → Type'
Var : Ctxt' → Type'
Pi : Ctxt' → Type' → Type' → Type'
data Ctxt-wf : Ctxt' → 𝒰 where
·-wf : Ctxt-wf ·
∷-wf : ∀ {Γ} {A} → Ctxt-wf Γ → Type-wf Γ A → Ctxt-wf (Γ ∷ A)
data Type-wf : Ctxt' → Type' → 𝒰 where
U-wf : ∀ {Γ} → Ctxt-wf Γ → Type-wf Γ (U Γ)
Var-wf : ∀ {Γ} → Ctxt-wf Γ → Type-wf (Γ ∷ U Γ) (Var Γ)
Pi-wf : ∀ {Γ} {A B} → Ctxt-wf Γ → Type-wf Γ A →
Type-wf (Γ ∷ A) B → Type-wf Γ (Pi Γ A B)
```

In other words, `Ctxt'`

and `Type'`

describe the syntax,
while `Ctxt-wf`

and `Type-wf`

describe the well-formedness rules.

```
Γ ⩴ · | Γ ∷ A (Ctxt')
A, B ⩴ U | Var | Π A B (Type' with Ctxt' argument omitted)
─── ·-wf
⊢ ·
⊢ Γ Γ ⊢ A
────────── ∷-wf
⊢ Γ ∷ A
⊢ Γ
────────── U-wf
Γ ⊢ U type
⊢ Γ
──────────────── Var-wf
Γ ∷ U ⊢ Var type
⊢ Γ Γ ⊢ A Γ ∷ A ⊢ B
───────────────────── Pi-wf
Γ ⊢ Π A B type
```

The final encoding of a context or a type is then the erased type paired with its well-formedness.

```
Ctxt = Σ[ Γ ∈ Ctxt' ] Ctxt-wf Γ
Type (Γ , Γ-wf) = Σ[ A ∈ Type' ] Type-wf Γ A
· = · , ·-wf
(Γ , Γ-wf) ∷ (A , A-wf) = Γ ∷ A , ∷-wf Γ-wf A-wf
U (Γ , Γ-wf) = U Γ , U-wf Γ-wf
Var (Γ , Γ-wf) = Var Γ , Var-wf Γ-wf
Pi (Γ , Γ-wf) (A , A-wf) (B , B-wf) = Pi Γ A B , Pi-wf Γ-wf A-wf B-wf
```

These indexed mutual inductives can then be transformed into a single indexed inductive with an additional index,
then into a nonuniformly parametrized inductive, and finally into an indexed W type.
The same technique can be applied to generalized inductive–inductives, e.g. “infinitary” `Pi`

.

```
data Type' : 𝒰 where
…
Pi∞ : Ctxt' → (ℕ → Type') → Type'
data Type-wf : Ctxt' → Type' → 𝒰 where
…
Pi∞-wf : ∀ {Γ} {T : ℕ → Type'} → Ctxt-wf Γ →
(∀ n → Type-wf Γ (T n)) → Type-wf Γ (Pi∞ Γ T)
Pi∞ (Γ , Γ-wf) TT-wf = Pi∞ Γ (fst ∘ TT-wf) , Pi∞-wf Γ-wf (snd ∘ TT-wf)
```

You can’t encode these as W types apparently.

*This section is lifted from Dan Doel’s encoding
of indexed W types as W types following the canonical construction from
Why Not W? by Jasper Hugunin.*

An indexed W type can be encoded as an unindexed one by first storing the index
together with the `A`

type as in `IW'`

below.
Then, define the `canonical`

predicate to assert that, given some index selector `d`

as would be found in an indexed well-founded tree,
not only is the current index the one we expect,
but the index of all recursive elements are the ones dictated by `d`

.
That is, `f b`

gives the actual recursive element from which we can extract the index,
while `d i a b`

gives the expected index, and we again assert their equality.
Finally, an encoded indexed W type `EIW`

is a `IW'`

type such that the index is canonical.

```
variable
I : 𝒰
A : I → 𝒰
B : ∀ i → A i → 𝒰
d : ∀ i → (a : A i) → B i a → I
IW' (I : 𝒰) →
(A : I → 𝒰) →
(B : ∀ i → A i → 𝒰) → 𝒰
IW' I A B = W (∃[ i ] A i) (λ (i , a) → B i a)
canonical : (∀ i → (a : A i) → B i a → I) → IW' I A B → I → 𝒰
canonical d (sup (i , a) f) i' = (i ≡ i') × (∀ b → canonical d (f b) (d i a b))
EIW : (I : 𝒰) →
(A : I → 𝒰) →
(B : ∀ i → A i → 𝒰) →
(d : ∀ i → (a : A i) → B i a → I) → I → 𝒰
EIW I A B d i = Σ[ w ∈ IW' I A B ] (canonical d w i)
isup : (i : I) → (a : A i) → ((b : B i a) → EIW I A B d (d i a b)) → EIW I A B d i
isup i a f = sup (i , a) (fst ∘ f) , refl i , (snd ∘ f)
```

Untyped conversion (and therefore reduction), I think, is meant to model the implementation of a conversion checker. (I’m really not the best person to ask.) Ideally, you’d want it to be entirely decoupled from the type checker, which is a very Software Engineering 110 reasonable thing to expect. An implementation outline might look like this:

- Reduce both terms sufficiently.
- If they look different, give up.
- Recur on subterms.

“Sufficiently” might mean normal form or weak head normal form or whatever reasonable form you like. So we might formalize that as follows:

```
───────────────────────── β
(λx: τ. e) e' ⊳ e[x ↦ e']
────── ⊳*-refl
e ⊳* e
e₁ ⊳ e₂
e₂ ⊳* e₃
──────── ⊳*-trans
e₁ ⊳* e₃
eᵢ ⊳* eᵢ'
─────────────────────── ⊳*-cong
e[x ↦ eᵢ] ⊳* e[x ↦ eᵢ']
e₁ ⊳* e
e₂ ⊳* e
─────── ≈-red
e₁ ≈ e₂
```

The “sufficiently” part comes from `⊳*-trans`

, where you take as many steps as you need.
The congruence rules are the most tedious, since you need one for every syntactic form,
so I’ve instead lazily written them as a single substitution.
Conversion is an equivalence relation, as you’d expect:
it’s reflexive (by `⊳*-refl`

), it’s symmetric (by swapping premises in `≈-red`

),
it’s substitutive (by `⊳*-cong`

), and it’s transitive *if* reduction is confluent,
because then you can construct the conversion by where the pairs meet.
(Confluence left as an exercise for the reader.)

```
e₁ ≈ e₂ ≈ e₃
\ / \ /
e₁₂ e₂₃ ← confluence gives this diamond
\ /
e*
e₁ ⊳* e*
e₃ ⊳* e*
────────
e₁ ≈ e₃
```

Dually to β, let’s now add η-contraction, but suppose we had cumulativity
(or more generally, *any* subtyping relation).
Then η-contraction is no good, since it breaks confluence.
Supposing we had types `σ ≤ τ`

, `λx: σ. (λy: τ. f y) x`

could either β-reduce to `λx: σ. f x`

,
or η-contract with congruence to `λy: τ. f y`

, but these are no longer α-equivalent due to the type annotation.
Breaking confluence then means breaking transitivity of conversion as well.
η-contraction then isn’t an option with Church-style type-annotated intrinsically-typed terms.

What about η-expansion? If you had a neutral term typed as a function, you may expand it once. But with untyped conversion, there’s no way to tell whether the term is indeed typed as a function, and you can’t go around η-expanding any old neutral term willy-nilly.

The remaining solution is then to add η-equivalence as part of conversion. There are two ways to do this; the first is the obvious way.

```
────────────── ≈-ηₗ (+ ≈-ηᵣ symmetrically)
λx: τ. f x ≈ f
```

This immediately requires explicit transitivity and congruence rules,
since `λx: τ. λy: σ. f x y ≈ f`

wouldn’t hold otherwise.
The other way is to check that one side is a function,
then apply the other side.

```
e₁ ⊳* λx: τ. e₁'
e₂ ⊳* e₂'
x ∉ FV(e₂')
e₁' ≈ e₂' x
──────────────── ≈-ηₗ (+ ≈-ηᵣ symmetrically)
e₁ ≈ e₂
```

This looks more ideal since it seems like it easily extends the implementation outline:

- Reduce both terms sufficiently.
- If one of them looks like a function, recur according to
`≈-η`

. - If they look different, give up.
- Recur on subterms.

You then still need congruence rules for step 4;
otherwise `F G ≈ F (λX: 𝒰. G X)`

would not hold given some `F: (𝒰 → 𝒰) → 𝒰`

and `G: 𝒰 → 𝒰`

.
It seems like transitivity *might* hold without explicitly adding it as a rule,
again by confluence, but this time requiring induction on derivation heights rather than structural induction,
and first showing that the derivation of any symmetric conversion has the same height.

Suppose we were in a setting with multiple syntactic functions, for instance the Calculus of Constructions or System F, where abstraction by and application of a type differs from ordinary term abstractions and applications.

```
Γ, x: σ ⊢ e: τ Γ, α: ⋆ ⊢ e : τ
─────────────────────── ─────────────────
Γ ⊢ λx: σ. e : Πx: σ. τ Γ ⊢ Λα. e : ∀α. τ
Γ ⊢ e : Πx: σ. τ Γ ⊢ e : ∀α. τ
Γ ⊢ e' : σ Γ ⊢ σ : ⋆
──────────────────── ────────────────────
Γ ⊢ e e' : τ[x ↦ e'] Γ ⊢ e [σ] : τ[α ↦ σ]
(λx: τ. e) e' ⊳ e[x ↦ e'] (Λα. e) [σ] ⊳ e[α ↦ σ]
```

If both of these functions had η-conversion rules, transitivity wouldn’t hold,
especially for open terms.
Specifically, the conversions `λx: τ. f x ≈ f`

and `f ≈ Λα. f [α]`

are both derivable
(despite being ill-typed when considered simultaneously, since conversion is untyped),
but `λx: τ. f x ≈ Λα. f [α]`

is impossible to derive.

In Oury’s Extensional Calculus of Constructions [2],
equality reflection is added to untyped conversion
(`≡`

denoting the equality *type*).

```
Γ ⊢ p: x ≡ y
──────────── ≈-reflect
Γ ⊢ x ≈ y
```

There’s a clash between the fact that ill-typed terms can still be convertible,
and that equality reflection only makes sense when everything is well-typed.
In particular, you cannot simultaneously have congruence and transitivity of conversion,
since it allows you to derive an inconsistency.
Concretely, using an ill-typed proof of `⊤ ≡ ⊥`

(where `⊤`

is trivially inhabited by `∗`

and `⊥`

is uninhabited),
you can convert from `⊤`

to `⊥`

.

```
· ⊢ ⊤ ≈ (λp: ⊤ ≡ ⊥. ⊤) refl (by β-reduction)
≈ (λp: ⊤ ≡ ⊥. ⊥) refl (by ≈-cong and ≈-reflect on (p: ⊤ ≡ ⊥) ⊢ p: ⊤ ≡ ⊥)
≈ ⊥ (by β-reduction)
```

Note the ill-typedness of the application:
`refl`

is clearly not a proof of `⊤ ≡ ⊥`

.
Evidently this leads to a contradiction,
since you could then convert the type of `∗`

from `⊤`

to `⊥`

.

Coq’s conversion algorithm can be found in its kernel,
which is actually one giant algorithm parametrized over whether it should be checking convertibility or cumulativity.
The below is my attempt at writing it down as rules (ignoring cases related to (co)inductives),
with MetaCoq’s conversion in pCuIC as guidance.
`[ʀ]`

represents the relation over which they are parametrized,
which can be either `[≈]`

or `[≤]`

.

```
i = j
────────── ≈-𝒰
𝒰ᵢ [≈] 𝒰ⱼ
i ≤ j
────────── ≤-𝒰
𝒰ᵢ [≤] 𝒰ⱼ
τ₁ [≈] τ₂
σ₁ [ʀ] σ₂
───────────────────────── ʀ-Π
Πx: τ₁. σ₁ [ʀ] Πx: τ₂. σ₂
t₁ [ʀ] t₂
e₁ [≈] e₂
─────────────── ʀ-app
t₁ e₁ [ʀ] t₂ e₂
τ₁ [≈] τ₂
e₁ [ʀ] e₂
───────────────────────── ʀ-λ
λx: τ₁. e₁ [ʀ] λx: τ₂. e₂
τ₁ [≈] τ₂
t₁ [≈] t₂
e₁ [ʀ] e₂
───────────────────────────────────────────── ʀ-let
let x: τ₁ ≔ t₁ in e₁ [ʀ] let x: τ₂ ≔ t₂ in e₂
e₁ [ʀ] e₂
─────────────────────── (catch-all for remaining syntactic constructs)
t[x ↦ e₁] [ʀ] t[x ↦ e₂]
e₂ x ⊳* e₂'
e₁ [≈] e₂'
──────────────── ʀ-ηₗ
λx: τ. e₁ [ʀ] e₂
e₁ x ⊳* e₁'
e₁' [≈] e₂
──────────────── ʀ-ηᵣ
e₁ [ʀ] λx: τ. e₂
```

The “real” conversion and subtyping rules are then the confluent closure of the above. The actual implementation performs more reduction as needed; I think this is just for performance reasons, and because there’s no way to forsee how many steps you’ll end up having to take during initial reduction.

```
e₁ ⊳* e₁'
e₂ ⊳* e₂'
e₁' [≈] e₂'
───────────
e₁ ≈ e₂
e₁ ⊳* e₁'
e₂ ⊳* e₂'
e₁' [≤] e₂'
───────────
e₁ ≤ e₂
```

Reflexivity and symmetry of conversion and reflexivity of subtyping are easy to see. Congruence is built into the rules (shown with the same substitution notation as before). Evidently conversion implies subtyping, but this time indirectly.

[1] McBride, Conor. (9 January 2015). *universe hierarchies*. ᴜʀʟ:https://pigworker.wordpress.com/2015/01/09/universe-hierarchies/.

[2] Oury, Nicolas. (TPHOLs 2005). *Extensionality in the Calculus of Constructions*. ᴅᴏɪ:10.1007/11541868_18.

While it’s rather difficult to accidentally prove an inconsistency in a well-meaning type theory that isn’t obviously inconsistent
(have you ever unintentionally proven that a type corresponding to an ordinal is strictly larger than itself? I didn’t think so),
it feels like it’s comparatively easy to add rather innocent features to your type theory that will suddenly make it inconsistent.
And there are so many of them!
And sometimes it’s the *interaction* among the features rather than the features themselves that produce inconsistencies.

As it turns out, a lot of the inconsistencies can surface as proofs of what’s known as Hurkens’ paradox [1], which is a simplification of Girard’s paradox [2], which itself is a type-theoretical formulation of the set-theoretical Burali–Forti’s paradox [3]. I won’t claim to deeply understand how any of these paradoxes work, but I’ll present various formulations of Hurkens’ paradox in the context of the most well-known inconsistent features.

The most common mechanization of Hurkens’ paradox you can find online is using type-in-type,
where the type of the universe `Type`

has `Type`

itself as its type,
because most proof assistants have ways of turning this check off.
We begin with what Hurkens calls a *powerful paradoxical universe*,
which is a type `U`

along with two functions `τ : ℘ (℘ U) → U`

and `σ : U → ℘ (℘ U)`

.
Conceptually, `℘ X`

is the powerset of `X`

, implemented as `X → Type`

;
`τ`

and `σ`

then form an isomorphism between `U`

and the powerset of its powerset, which is an inconsistency.
Hurkens defines `U`

, `τ`

, and `σ`

as follows, mechanized in Agda below.

```
U : Set
U = ∀ (X : Set) → (℘ (℘ X) → X) → ℘ (℘ X)
τ : ℘ (℘ U) → U
τ t = λ X f p → t (λ x → p (f (x X f)))
σ : U → ℘ (℘ U)
σ s = s U τ
```

The complete proof can be found at Hurkens.html, but we’ll focus on just these definitions for the remainder of this post.

Hurkens’ original construction of the paradox was done in System U⁻, where there are *two* impredicative universes,
there named `*`

and `□`

.
We’ll call ours `Set`

and `Set₁`

, with the following typing rules for function types featuring impredicativity.

```
Γ ⊢ A : 𝒰
Γ, x: A ⊢ B : Set
────────────────── Π-Set
Γ ⊢ Πx: A. B : Set
Γ ⊢ A : 𝒰
Γ, x: A ⊢ B : Set₁
─────────────────── Π-Set₁
Γ ⊢ Πx: A. B : Set₁
```

Going back to the type-in-type proof, consider now `℘ (℘ X)`

.
By definition, this is `(X → Set) → Set`

; since `Set : Set₁`

, by Π-Set₁,
the term has type `Set₁`

, regardless of what the type of `X`

is.
Then `U = ∀ X → (℘ (℘ X) → X) → ℘ (℘ X)`

has type `Set₁`

as well.
Because later when defining `σ : U → ℘ (℘ U)`

, given a term `s : U`

, we want to apply it to `U`

,
the type of `X`

should have the same type as `U`

for `σ`

to type check.
The remainder of the proof of inconsistency is unchanged, as it doesn’t involve any explicit universes,
although we also have the possibility of lowering the return type of `℘`

.
An impredicative `Set₁`

above a predicative `Set`

may be inconsistent as well,
since we never make use of the impredicativity of `Set`

itself.

```
℘ : ∀ {ℓ} → Set ℓ → Set₁
℘ {ℓ} S = S → Set
U : Set₁
U = ∀ (X : Set₁) → (℘ (℘ X) → X) → ℘ (℘ X)
```

Note well that having two impredicative universe layers is *not* the same thing as having two parallel impredicative universes.
For example, by turning on `-impredicative-set`

in Coq, we’d have an impredicative `Prop`

and an impredicative `Set`

,
but they are in a sense parallel universes: the type of `Prop`

is `Type`

, not `Set`

.
The proof wouldn’t go through in this case, since it relies on the type of the return type of `℘`

being impredicative as well.
With cumulativity, `Prop`

is a subtype of `Set`

, but this has no influence for our puposes.

A *strong (dependent) pair* is a pair from which we can project its components.
An *impredicative pair* in some impredicative universe `𝒰`

is a pair that lives in `𝒰`

when either of its components live in `𝒰`

,
regardless of the universe of the other component.
It doesn’t matter too much which specific universe is impredicative as long as we can refer to both it and its type,
so we’ll suppose for this section that `Set`

is impredicative.
The typing rules for the strong impredicative pair are then as follows;
we only need to allow the first component of the pair to live in any universe.

```
Γ ⊢ A : 𝒰
Γ, x: A ⊢ B : Set
──────────────────
Γ ⊢ Σx: A. B : Set
Γ ⊢ a : A
Γ ⊢ b : B[x ↦ a]
─────────────────────
Γ ⊢ (a, b) : Σx: A. B
Γ ⊢ p : Σx: A. B
────────────────
Γ ⊢ fst p : A
Γ ⊢ p : Σx: A. B
────────────────────────
Γ ⊢ snd p : B[x ↦ fst p]
Γ ⊢ (a, b) : Σx: A. B
──────────────────────
Γ ⊢ fst (a, b) ≡ a : A
Γ ⊢ (a, b) : Σx: A. B
─────────────────────────────
Γ ⊢ snd (a, b) ≡ b : B[x ↦ a]
```

If we turn type-in-type off in the previous example, the first place where type checking fails is for `U`

,
which with predicative universes we would expect to have type `Set₁`

.
The idea, then, is to squeeze `U`

into the lower universe `Set`

using the impredicativity of the pair,
then to extract the element of `U`

as needed using the strongness of the pair.
Notice that we don’t actually need the second component of the pair, which we can trivially fill in with `⊤`

.
This means we could instead simply use the following record type in Agda.

```
record Lower (A : Set₁) : Set where
constructor lower
field raise : A
```

The type `Lower A`

is equivalent to `Σx: A. ⊤`

, its constructor `lower a`

is equivalent to `(a, tt)`

,
and the projection `raise`

is equivalent to `fst`

.
To allow type checking this definition, we need to again turn on type-in-type, despite never actually exploiting it.
If we really want to make sure we really never make use of type-in-type,
we can postulate `Lower`

, `lower`

, and `raise`

, and use rewrite rules to recover the computational behaviour of the projection.

```
{-# OPTIONS --rewriting #-}
postulate
Lower : (A : Set₁) → Set
lower : ∀ {A} → A → Lower A
raise : ∀ {A} → Lower A → A
beta : ∀ {A} {a : A} → raise (lower a) ≡ a
{-# REWRITE beta #-}
```

Refactoring the existing proof is straightforward:
any time an element of `U`

is used, it must first be raised back to its original universe,
and any time an element of `U`

is produced, it must be lowered down to the desired universe.

```
U : Set
U = Lower (∀ (X : Set) → (℘ (℘ X) → X) → ℘ (℘ X))
τ : ℘ (℘ U) → U
τ t = lower (λ X f p → t (λ x → p (f (raise x X f))))
σ : U → ℘ (℘ U)
σ s = raise s U τ
```

Again, the complete proof can be found at HurkensLower.html.
One final thing to note is that impredicativity (with respect to function types) of `Set`

isn’t used either;
all of this code type checks in Agda, whose universe `Set`

is not impredicative.
This means that impredicativity with respect to strong pair types alone is sufficient for inconsistency.

In contrast to strong pairs, weak (impredicative) pairs don’t have first and second projections.
Instead, to use a pair, one binds its components in the body of some expression
(continuing our use of an impredicative `Set`

).

```
Γ ⊢ p : Σx: A. B
Γ, x: A, y: B ⊢ e : C
Γ ⊢ C : Set
────────────────────────────
Γ ⊢ let (x, y) := p in e : C
```

The key difference is that the type of the expression must live in `Set`

, and not in any arbitrary universe.
Therefore, we can’t generally define our own first projection function, since `A`

might not live in `Set`

.

Weak impredicative pairs can be generalized to inductive types in an impredicative universe,
where the restriction becomes disallowing arbitrary *large elimination* to retain consistency.
This appears in the typing rule for case expressions on inductives.

```
Γ ⊢ t : I p… a…
Γ ⊢ I p… : (y: u)… → 𝒰
Γ, y: u, …, x: I p… a… ⊢ P : 𝒰'
elim(𝒰, 𝒰') holds
< other premises omitted >
───────────────────────────────────────────────────────────────
Γ ⊢ case t return λy…. λx. P of [c x… ⇒ e]… : P[y… ↦ a…][x ↦ t]
```

The side condition `elim(𝒰, 𝒰')`

holds if:

`𝒰 = Set₁`

or higher; or`𝒰 = 𝒰' = Set`

; or`𝒰 = Set`

and- Its constructors’ arguments are either forced or have types living in
`Set`

; and - The fully-applied constructors have orthogonal types; and
- Recursive appearances of the inductive type in the constructors’ types are syntactically guarded.

- Its constructors’ arguments are either forced or have types living in

The three conditions of the final case come from the rules for definitionally proof-irrelevant `Prop`

[4];
the conditions that Coq uses are that the case target’s inductive type must be a singleton or empty,
which is a subset of those three conditions.
As the pair constructor contains a non-forced, potentially non-`Set`

argument in the first component,
impredicative pairs can only be eliminated to terms whose types are in `Set`

,
which is exactly what characterizes the weak impredicative pair.
On the other hand, allowing unrestricted large elimination lets us define not only strong impredicative pairs,
but also `Lower`

(and the projection `raise`

), both as inductive types.

While impredicative functions can Church-encode weak impredicative pairs, they can’t encode strong ones.

```
Σx: A. B ≝ (P : Set) → ((x : A) → B → P) → P
```

If `Set`

is impredicative then the pair type itself lives in `Set`

,
but if `A`

lives in a larger universe, then it can’t be projected out of the pair,
which requires setting `P`

as `A`

.

There’s a variety of other features that yield inconsistencies in other ways, some of them resembling the set-theoretical Russell’s paradox.

A negative inductive type is one where the inductive type appears to the left of an odd number of arrows in a constructor’s type. For instance, the following definition will allow us to derive an inconsistency.

```
record Bad : Set where
constructor mkBad
field bad : Bad → ⊥
open Bad
```

The field of a `Bad`

essentially contains a negation of `Bad`

itself (and I believe this is why this is considered a “negative” type).
So when given a `Bad`

, applying it to its own field, we obtain its negation.

```
notBad : Bad → ⊥
notBad b = b.bad b
```

Then from the negation of `Bad`

we construct a `Bad`

, which we apply to its negation to obtain an inconsistency.

```
bottom : ⊥
bottom = notBad (mkBad notBad)
```

*This section is adapted from Why must inductive types be strictly positive?*.

A positive inductive type is one where the inductive type appears to the left of an even number of arrows in a constructor’s type.
(Two negatives cancel out to make a positive, I suppose.)
If it’s restricted to appear to the left of *no* arrows (0 is an even number), it’s a *strictly* positive inductive type.
Strict positivity is the usual condition imposed on all inductive types in Coq.
If instead we allow positive inductive types in general, when combined with an impredicative universe (we’ll use `Set`

again),
we can define an inconsistency corresponding to Russell’s paradox.

```
{-# NO_POSITIVITY_CHECK #-}
record Bad : Set₁ where
constructor mkBad
field bad : ℘ (℘ Bad)
```

From this definition, we can prove an injection from `℘ Bad`

to `Bad`

via an injection from `℘ Bad`

to `℘ (℘ Bad)`

defined as a partially-applied equality type.

```
f : ℘ Bad → Bad
f p = mkBad (_≡ p)
fInj : ∀ {p q} → f p ≡ f q → p ≡ q
fInj {p} fp≡fq = subst (λ p≡ → p≡ p) (badInj fp≡fq) refl
where
badInj : ∀ {a b} → mkBad a ≡ mkBad b → a ≡ b
badInj refl = refl
```

Evidently an injection from a powerset of some `X`

to `X`

itself should be an inconsistency.
However, it doesn’t appear to be provable without using some sort of impredicativity.
(We’ll see.)
Coquand and Paulin [5] use the following definitions in their proof, which does not type check without type-in-type,
since `℘ Bad`

otherwise does not live in `Set`

.
In this case, weak impredicative pairs would suffice, since the remaining definitions can all live in the same impredicative universe.

```
P₀ : ℘ Bad
P₀ x = Σ[ P ∈ ℘ Bad ] x ≡ f P × ¬ (P x)
x₀ : Bad
x₀ = f P₀
```

From here, we can prove `P₀ x₀ ↔ ¬ P₀ x₀`

. The rest of the proof can be found at Positivity.html.

Another type-theoretic encoding of Russell’s paradox is Berardi’s paradox [6]. It begins with a retraction, which looks like half an isomorphism.

```
record _◁_ {ℓ} (A B : Set ℓ) : Set ℓ where
constructor _,_,_
field
ϕ : A → B
ψ : B → A
retract : ψ ∘ ϕ ≡ id
open _◁_
```

We can easily prove `A ⊲ B → A ⊲ B`

by identity.
If we postulate the axiom of choice, then we can push the universal quantification over `A ⊲ B`

into the existential quantification of `A ⊲ B`

,
yielding a `ϕ`

and a `ψ`

such that `ψ ∘ ϕ ≡ id`

only when given some proof of `A ⊲ B`

.
However, a retraction of powersets can be stipulated out of thin air using only the axiom of excluded middle.

```
record _◁′_ {ℓ} (A B : Set ℓ) : Set ℓ where
constructor _,_,_
field
ϕ : A → B
ψ : B → A
retract : A ◁ B → ψ ∘ ϕ ≡ id
open _◁′_
postulate
EM : ∀ {ℓ} (A : Set ℓ) → A ⊎ (¬ A)
t : ∀ {ℓ} (A B : Set ℓ) → ℘ A ◁′ ℘ B
t A B with EM (℘ A ◁ ℘ B)
... | inj₁ ℘A◁℘B =
let ϕ , ψ , retract = ℘A◁℘B
in ϕ , ψ , λ _ → retract
... | inj₂ ¬℘A◁℘B =
(λ _ _ → ⊥) , (λ _ _ → ⊥) , λ ℘A◁℘B → ⊥-elim (¬℘A◁℘B ℘A◁℘B)
```

This time defining `U`

to be `∀ X → ℘ X`

, we can show that `℘ U`

is a retract of `U`

.
Here, we need an impredicative `Set`

so that `U`

can also live in `Set`

and so that `U`

quantifies over itself as well.
Note that we project the equality out of the record while the record is impredicative,
so putting `_≡_`

in `Set`

as well will help us avoid large eliminations for now.

```
projᵤ : U → ℘ U
projᵤ u = u U
injᵤ : ℘ U → U
injᵤ f X =
let _ , ψ , _ = t X U
ϕ , _ , _ = t U U
in ψ (ϕ f)
projᵤ∘injᵤ : projᵤ ∘ injᵤ ≡ id
projᵤ∘injᵤ = retract (t U U) (id , id , refl)
```

Now onto Russell’s paradox.
Defining `_∈_`

to be `projᵤ`

and letting `r ≝ injᵤ (λ u → ¬ u ∈ u)`

,
we can show a curious inconsistent statement.

```
r∈r≡r∉r : r ∈ r ≡ (¬ r ∈ r)
r∈r≡r∉r = cong (λ f → f (λ u → ¬ u ∈ u) r) projᵤ∘injᵤ
```

To actually derive an inconsistency, we can derive functions `r ∈ r → (¬ r ∈ r)`

and `(¬ r ∈ r) → r ∈ r`

using substitution,
then prove falsehood the same way we did for negative inductive types.
However, the predicate in the substitution is `Set → Set`

, which itself has type `Set₁`

,
so these final steps do require unrestricted large elimination.
The complete proof can be found at Berardi.html.

Having impredicative inductive types that can be eliminated to large types can yield an inconsistency
without having to go through Hurkens’ paradox.
To me, at least, this inconsistency is a lot more comprehensible.
This time, we use an impredicative representation of the ordinals [7],
prove that they are well-founded with respect to some reasonable order on them,
then prove a falsehood by providing an ordinal that is obviously *not* well-founded.
This representation can be type checked using Agda’s `NO_UNIVERSE_CHECK`

pragma,
and normally it would live in `Set₁`

due to one constructor argument type living in `Set₁`

.

```
{-# NO_UNIVERSE_CHECK #-}
data Ord : Set where
↑_ : Ord → Ord
⊔_ : {A : Set} → (A → Ord) → Ord
data _≤_ : Ord → Ord → Set where
↑s≤↑s : ∀ {r s} → r ≤ s → ↑ r ≤ ↑ s
s≤⊔f : ∀ {A} {s} f (a : A) → s ≤ f a → s ≤ ⊔ f
⊔f≤s : ∀ {A} {s} f → (∀ (a : A) → f a ≤ s) → ⊔ f ≤ s
```

An ordinal is either a successor ordinal, or a limit ordinal.
(The zero ordinal could be defined as a limit ordinal.)
Intuitively, a limit ordinal `⊔ f`

is the supremum of all the ordinals returned by `f`

.
This is demonstrated by the last two constructors of the preorder on ordinals:
`s≤⊔f`

states that `⊔ f`

is an upper bound of all the ordinals of `f`

,
while `⊔f≤s`

states that it is the *least* upper bound.
Finally, `↑s≤↑s`

is simply the monotonicity of taking the successor of an ordinal with respect to the preorder.
It’s possible to show that `≤`

is indeed a preorder by proving its reflexivity and transitivity.

```
s≤s : ∀ {s : Ord} → s ≤ s
s≤s≤s : ∀ {r s t : Ord} → r ≤ s → s ≤ t → r ≤ t
```

From the preorder we define a corresponding strict order.

```
_<_ : Ord → Ord → Set
r < s = ↑ r ≤ s
```

In a moment, we’ll see that `<`

can be proven to be *wellfounded*,
which is equivalent to saying that in that there are no infinite descending chains.
Obviously, for there to be no such chains, `<`

must at minimum be irreflexive — but it’s not!
There is an ordinal that is strictly less than itself,
which we’ll call the “infinite” ordinal,
defined as the limit ordinal of *all* ordinals,
which is possible due to the impredicativity of `Ord`

.

```
∞ : Ord
∞ = ⊔ (λ s → s)
∞<∞ : ∞ < ∞
∞<∞ = s≤⊔f (λ s → s) (↑ ∞) s≤s
```

To show wellfoundedness, we use an *accessibility predicate*,
whose construction for some ordinal `s`

relies on showing that all smaller ordinals are also accessible.
Finally, wellfoundness is defined as a proof that *all* ordinals are accessible,
using a lemma to extract accessibility of all smaller or equal ordinals.

```
record Acc (s : Ord) : Set where
inductive
pattern
constructor acc
field
acc< : (∀ r → r < s → Acc r)
accessible : ∀ (s : Ord) → Acc s
accessible (↑ s) = acc (λ { r (↑s≤↑s r≤s) → acc (λ t t<r → (accessible s).acc< t (s≤s≤s t<r r≤s)) })
accessible (⊔ f) = acc (λ { r (s≤⊔f f a r<fa) → (accessible (f a)).acc< r r<fa })
```

But wait, we needed impredicativity *and* large elimination.
Where is the large elimination?

It turns out that it’s hidden within Agda’s pattern-matching mechanism.
Notice that in the limit case of `accessible`

, we only need to handle the `s≤⊔f`

case,
since this is the only case that could possibly apply when the left side is a successor and the right is an ordinal.
However, if you were to write this in plain CIC for instance,
you’d need to first explicitly show that the order could not be either of the other two constructors,
requiring showing that the successor and limit ordinals are provably distinct
(which itself needs large elimination, although this is permissible as an axiom),
then due to the proof architecture show that if two limit ordinals are equal, then their components are equal.
This is known as *injectivity of constructors*.
Expressing this property for ordinals requires large elimination,
since the first (implicit) argument of limit ordinals are in `Set`

.

You can see how it works explicitly by writing the same proof in Coq,
where the above steps correspond to inversion followed by dependent destruction,
then printing out the full term.
The `s≤⊔f`

subcase of the `⊔ f`

case alone spans 50 lines!

In any case, we proceed to actually deriving the inconsistency, which is easy:
show that `∞`

is in fact *not* accessible using `∞<∞`

,
then derive falsehood directly.

```
¬accessible∞ : Acc ∞ → ⊥
¬accessible∞ (acc p) = ¬accessible∞ (p ∞ ∞<∞)
ng : ⊥
ng = ¬accessible∞ (accessible ∞)
```

The complete Agda proof can be found at Ordinals.html, while a partial Coq proof of accessibility of ordinals can be found at Ordinals.html.

The recursive calls of cofixpoints must be *guarded by constructors*,
meaning that they only appear as arguments to constructors of the coinductive type of the cofixpoint.
What’s more, the constructor argument type must be syntactically the coinductive type,
not merely a polymorphic type that’s filled in to be the coinductive type later.
If the guardedness condition is relaxed to ignore this second condition,
then we can derive an inconsistency with impredicative coinductives.
Again, we define one using `NO_UNIVERSE_CHECK`

, with contradictory fields.
Evidently we should never be able to construct such a coinductive.

```
{-# NO_UNIVERSE_CHECK #-}
record Contra : Set where
coinductive
constructor contra
field
A : Set
a : A
¬a : A → ⊥
¬c : Contra → ⊥
¬c = λ c → (¬a c) (a c)
```

However, if the type field in `Contra`

is `Contra`

itself,
then we can in fact construct one coinductively.
Here, we use `NON_TERMINATING`

to circumvent Agda’s perfectly correct guardedness checker,
but notice that the recursive call is inside of `contra`

and therefore still “guarded”.
This easily leads to an inconsistency.

```
{-# NON_TERMINATING #-}
c : Contra
c = contra Contra c ¬c
ng : ⊥
ng = ¬c c
```

This counterexample is due to Giménez [8] and the complete proof can be found at Coind.html.

The combinations of features that yield inconsistencies are:

- Type-in-type:
`· ⊢ Set : Set`

- Impredicative
`Set`

and`Set₁`

where`· ⊢ Set : Set₁`

- Strong impredicative pairs
- Impredicative inductive types + unrestricted large elimination
- Negative inductive types
- Non-strictly-positive inductive types + impredicativity
- Impredicativity + excluded middle + unrestricted large elimination
- Impredicative inductive types + unrestricted large elimination (again)
- Relaxed guardedness of cofixpoints

`Lower`

: HurkensLower.html[1] Hurkens, Antonius J. C. (TLCA 1995). *A Simplification of Girard’s Paradox*. ᴅᴏɪ:10.1007/BFb0014058.

[2] Coquand, Thierry. (INRIA 1986). *An Analysis of Girard’s Paradox*. https://hal.inria.fr/inria-00076023.

[3] Burali–Forti, Cesare. (RCMP 1897). *Una questione sui numeri transfini*. ᴅᴏɪ:10.1007/BF03015911.

[4] Gilbert, Gaëtan; Cockx, Jesper; Sozeau, Matthieu; Tabareau, Nicolas. (POPL 2019). *Definitional Proof-Irrelevance without K*. ᴅᴏɪ:10.1145/3290316.

[5] Coquand, Theirry; Paulin, Christine. (COLOG 1988). *Inductively defined types*. ᴅᴏɪ:10.1007/3-540-52335-9_47.

[6] Barbanera, Franco; Berardi, Stefano. (JFP 1996). *Proof-irrelevance out of excluded middle and choice in the calculus of constructions*. ᴅᴏɪ:10.1017/S0956796800001829.

[7] Pfenning, Frank; Christine, Paulin-Mohring. (MFPS 1989). *Inductively defined types in the Calculus of Constructions*. ᴅᴏɪ:10.1007/BFb0040259.

[8] Giménez, Eduardo. (TYPES 1994). *Codifying guarded definitions with recursive schemes*. ᴅᴏɪ:10.1007/3-540-60579-7_3.

It was a miracle I ended up mostly physically unscathed. I instinctively shot out my arms underneath me and I could have broken a wrist or two. I could’ve landed on my tailbone wrong and broken that too. But it seemed the only damage was a light bruise on my sacrum (had to look up the word for that) and to my ego. Not even a scratch on my palms! Then I sat down, took out my laptop, opened it, and discovered the large crack from the bottom left corner, reaching longingly to conquer the entirety of the screen.

This step is really important.
If you don’t wallow in the despair now, when you’re powerless on the bus,
the despair will overtake you when you actually want to take action.
Allow it to pass over and through you.^{1}
Now we are ready to fix the screen.

I remembered a friend in my research lab had also replaced their ThinkPad screen, who got their replacement from Laptop Screen. Searching for my model, I found the appropriate replacement; unfortunately I couldn’t upgrade from FHD to QHD, because the former uses a 30-pin connected while the latter 40-pin, but I could upgrade to an IPS screen with “professional colour”, if that even makes a noticeable difference.

Even though I could’ve transited to their warehouse in under an hour and a half,
there wasn’t a pickup option, so I had to pay 9.86$ for shipping and 2.53$ for insurance.
Then with GST and PST, the total came to **163.22$**.
High price for a slipping accident.

I ordered it on Friday and they managed to get it shipped the same day, but since Canada Post doesn’t deliver on weekends, I had to wait out the weekend. I spent this time setting up my brother’s monitor temporarily and making the crack worse because I couldn’t resist.

In other news the laptop screen is not doing great. idk if you can see the flickering but this has gone from "I can use ¾ of the screen I guess" to "no ❤️" pic.twitter.com/1XBET9qeem

— 🥢 {#- OPTIONS --sized-types -#} 🎃 (@ionathanch) October 23, 2021

Now it’s time for the fun part: replacing the screen. Before I started, I watched through this tutorial, which was pretty close to how my model (the ThinkPad T480s) works. I first peeled off the soft plastic bezel that was attached on with long, black adhesive strips. I didn’t have a spudger, so I did accidentally scratch one part of the outside of the bezel with my flathead. Some of the adhesive strips were left stuck to the screen, so I had to peel them off and stick them back on the bezel.

Next part is easy: Remove the four screws holding the screen in place and unplug the 30-pin connector. There’s this thin metal latch that folds down to secure the plug; it has to be flipped up first. I didn’t notice it at first, because I wasn’t expecting it from what I saw in the tutorial, and I was nearly about to rip the cable in half.

Now I can plug in the new screen, flip the latch down, turn on my computer briefly to test the screen, screw the new screen in firmly, peel off the protective plastic, and finally put the bezel back. This was probably the most difficult step and took me three tries to get it aligned correctly. And it’s done! The screen looks brand new (because it is), and you can barely tell where I scratched the bezel.

Preferrably one with very padded sides to prevent similar drop damage. I don’t want to have to spend another 163.22$ for my mistakes.

^{1}
Excuse the reference, Dune (2021) with Paul played by renowned twink Timothée Chalamet just came out a few days ago.

*This post is inspired by this thread
from the Agda mailing list.*

Because Agda treats `Size`

like a first-class type,
there’s quite a bit of freedom in how you get to use it.
This makes it a bit unclear where you should start:
should `Size`

be a parameter or an index in your type?
What sizes should the constructors’ recursive arguments’ and return types have?
Here are two options that are usually used (and one that doesn’t work.)
The recommended one is using inflationary sized types and `Size<`

.

We’ll be looking at adding sized types to a mutually-defined tree/forest inductive type.
A tree parametrized by `A`

contains an `A`

and a forest,
while a forest consists of a bunch of trees.

```
{-# OPTIONS --sized-types #-}
open import Size
variable
A : Set
module Forestry where
data Tree {A : Set} : Set
data Forest {A : Set} : Set
data Tree {A} where
node : A → Forest {A} → Tree
data Forest {A} where
leaf : Forest
cons : Tree {A} → Forest {A} → Forest
traverse : (Tree {A} → Tree {A}) → Forest {A} → Forest {A}
traverse f leaf = leaf
-- traverse f (cons (node a forest) rest) = cons (f (node a (traverse f forest))) (traverse f rest)
traverse f (cons tree rest) with f tree
... | node a forest = cons (node a (traverse f forest)) (traverse f rest)
```

We can traverse a forest with a function that acts on trees. The first (commented out) is to first traverse the forest contained within a tree, then apply the function to the tree, which is structurally guarded. The second is to traverse the forest of the tree applied to the function, which is not. However, if we promise to not alter the size of the tree with our function—that is, using a size-preserving function—then we’ll be able to implement this post-traversal.

Here’s a recipe for turning your inductives into sized inductives.

- In the types of the inductives, add
`Size`

as an index. - For every constructor, add a size argument
`∀ s`

. - For every recursive constructor argument (that includes the mutual ones), give it size
`s`

. - For every constructor return type, give it size
`↑ s`

.

I call this pattern *successor* sized types since every constructible inductive’s size is a successor size.
Then it will always have a larger size than any of its recursive arguments.
I tend to keep the sizes in the inductives’ types explicit,
so that size-preserving function signatures are clear,
but make the sizes in the constructors’ types implicit,
since those can usually be inferred when the sizes are present in the function signatures.
Applied to trees and forests, this is what we get.

```
module SuccSizedForestry where
data Tree {A : Set} : Size → Set
data Forest {A : Set} : Size → Set
data Tree {A} where
node : ∀ {s} → A → Forest {A} s → Tree (↑ s)
data Forest {A} where
leaf : ∀ {s} → Forest (↑ s)
cons : ∀ {s} → Tree {A} s → Forest {A} s → Forest (↑ s)
```

The traversal function is easy: just add the sizes in the type, and type checking will do the rest.

```
traverse : ∀ {s} → (∀ {r} → Tree {A} r → Tree {A} r) → Forest {A} s → Forest {A} s
traverse f leaf = leaf
traverse f (cons tree rest) with f tree
... | node a forest = cons (node a (traverse f forest)) (traverse f rest)
```

There’s one strange thing with our current definition:
in `cons`

, the tree and the forest need to have the same size.
Given that they’re not only two different arguments but also two arguments of different types,
why should they have the same size?
When constructing a forest, you’ll certainly run into the issue of
needing to bump up the size of one or the other in order to use `cons`

.
Let’s see if we can avoid this by using different sizes.

Spoiler alert: this doesn’t pass termination checking in Agda… but let’s proceed anyway. The recipe is modified slightly.

- In the types of the inductives, add
`Size`

as an index. - For every constructor, add a size argument
`∀ sᵢ`

for each of the recursive arguments. - For each
`i`

th recursive constructor argument, give it size`sᵢ`

. - For every constructor return type with
`n`

recursive arguments, you have two options:- Give it size
`↑ (s₁ ⊔ˢ s₂ ⊔ˢ ... ⊔ˢ sₙ)`

; or - Give it size
`(↑ s₁) ⊔ˢ (↑ s₂) ⊔ˢ ... ⊔ˢ (↑ sₙ)`

.

- Give it size

The supremum operator `s₁ ⊔ˢ s₂`

can be thought of as taking the maximum of the two sizes.
The idea is that if you have two arguments of size `s₁`

and `s₂`

,
the size of the constructed term should have a size larger than whichever is largest,
and `↑ (s₁ ⊔ˢ s₂)`

and `(↑ s₁) ⊔ˢ (↑ s₂)`

are equivalent.
I’ve chosen the former below.

```
module SupSizedForestry where
data Tree {A : Set} : Size → Set
data Forest {A : Set} : Size → Set
data Tree {A} where
node : ∀ {s} → A → Forest {A} s → Tree (↑ s)
data Forest {A} where
leaf : ∀ {s} → Forest (↑ s)
cons : ∀ {st sf} → Tree {A} st → Forest {A} sf → Forest (↑ (st ⊔ˢ sf))
-- cons : ∀ {st sf} → Tree {A} st → Forest {A} sf → Forest ((↑ st) ⊔ˢ (↑ sf))
```

However, the traversal doesn’t pass termination checking. I’ve specified some of the sizes explicitly for clarity.

```
traverse : ∀ {s} → (∀ {r} → Tree {A} r → Tree {A} r) → Forest {A} s → Forest {A} s
traverse f leaf = leaf
traverse f (cons tree forest) with f tree
traverse {_} .{↑ ((↑ st) ⊔ˢ sf)} f (cons .{↑ st} {sf} tree forest)
| (node {st} a forest') = cons (node a (traverse {_} {st} f forest')) (traverse {_} {sf} f forest)
```

It appears that Agda can’t deduce that `st`

and `sf`

are both strictly smaller than `↑ ((↑ st) ⊔ˢ sf)`

.
(To see that this is true, if `sf > ↑ st`

, then `↑ ((↑ st) ⊔ˢ sf) = ↑ sf > sf > ↑ st`

;
otherwise, `↑ ((↑ st) ⊔ˢ sf) = ↑ ↑ st > ↑ st ≥ sf`

.)

The last option does work in Agda, and has the benefit of allowing different sizes for different arguments. Overall, this is the ideal option to choose. The first option is more of a historical artifact than anything. The recipe is a little different:

- In the types of the inductives, add
`(s : Size)`

as a*parameter*. - For every constructor, add a size argument
`∀ (rᵢ : Size< s)`

for each of the recursive arguments. - For each
`i`

th recursive constructor argument, give it size`rᵢ`

. - The return types of the constructors necessarily have size
`s`

, since it’s a parameter.

The `Size< : Size → Set`

type constructor lets us declare a size strictly smaller than a given size.
Then just as in the first option, every recursive argument must have a smaller size.
These are called inflationary sized types because they correspond to inflationary fixed points in the metatheory,
but I prefer to simply think of them as *bounded* sized types.

```
module BoundedSizedForestry where
data Tree {A : Set} (s : Size) : Set
data Forest {A : Set} (s : Size) : Set
data Tree {A} s where
node : ∀ {r : Size< s} → A → Forest {A} r → Tree s
data Forest {A} s where
leaf : ∀ {r : Size< s} → Forest s
cons : ∀ {st sf : Size< s} → Tree {A} st → Forest {A} sf → Forest s
```

Then the traversal is exactly the same as in the first option, and passes termination checking without any further effort.

```
traverse : ∀ {s} → (∀ {r} → Tree {A} r → Tree {A} r) → Forest {A} s → Forest {A} s
traverse f leaf = leaf
traverse f (cons tree rest) with f tree
... | node a forest = cons (node a (traverse f forest)) (traverse f rest)
```

*This example is lifted from issue #2820 in the Agda GitHub repository.*

Agda’s sized types comes with an infinite size `∞`

that you can sprinkle in anywhere.
This is handy for specifying sized arguments whose size you don’t care about
(e.g. if you’re not recurring on them),
and for specifying sized return types that are “too big” to be expressible as a finite size,
such as the return type of a factorial function.
In order for `∞`

to behave as you’d expect, it needs to satisfy `∞ + 1 = ∞`

,
which implies `∞ + 1 < ∞`

.
However, we can also show that the order `<`

on sizes is well-founded,
thus yielding a contradiction in the presence of `∞`

.

Agda already has an order on sizes via `Size<`

, but this is hard to manipulate.
We can instead define an inductive type that reflects this order.

```
module False where
open import Data.Empty
data _<_ : Size → Size → Set where
lt : ∀ s → (r : Size< s) → r < s
```

Next, we define accessibility with respect to this order, which states that for some size `s`

,
if every smaller size is accessible, then `s`

itself is accessible.
Agda’s standard library has an accessibility relation parametrized over an arbitrary order,
but I’ll redefine it explicitly for sizes for clarity.

```
data Acc (s : Size) : Set where
acc : (∀ {r} → r < s → Acc r) → Acc s
```

Now we can state wellfoundedness of sizes, which is simply that every size is accessible.
If this is true, then surely there should be no infinitely-descending chain `... s₃ < s₂ < s₁`

.

```
wf : ∀ s → Acc s
wf s = acc (λ {(lt .s r) → wf r})
```

This proof appears to rely on the fact that the type of `r`

gets unified with `Size< s`

when matching on `r < s`

.
Then termination checking passes because `wf`

is called on a smaller size.
Conventionally, this kind of proof is structurally-decreasing based on case analysis of the thing that’s accessible,
but we can’t inspect sizes like that in Agda.

The problem with saying that sizes are wellfounded with respect to the size order is that they are not!
We have the infinitely-descending chain `... ∞ < ∞ < ∞`

.
The fact that `∞`

is *not* accessible can be proven by structural induction on the accessibility relation,
without the help of sized termination checking.

```
¬wf∞ : Acc ∞ → ⊥
¬wf∞ (acc p) = ¬wf∞ (p (lt ∞ ∞))
```

Finally, we prove falsehood from this and the contradictory fact that `∞`

is wellfounded
because we’ve just proven that *all* sizes are wellfounded.

```
ng : ⊥
ng = ¬wf∞ (wf ∞)
```

*If you’re already familiar with sized types, in particular the kind that Agda has,
you can skip to the next section.
However, I do introduce my own syntax for sized types here.*

Sized types are all about type-based termination checking: if a program is well-typed, then we can be sure that its execution will terminate. Practically speaking, information about the relative difference in syntatic size of an inductive construction is stored in the type of the inductive. Using the classic example of the naturals, we can augment its inductive definition with sizes.

```
data Nat : Set where
zero : Nat
succ : Nat → Nat
data Nat [α] : Set where
zero : ∀β < α. Nat [α]
succ : ∀β < α. Nat [β] → Nat [α]
```

This says that `Nat`

takes some size parameter `α`

, and to construct a `Nat`

of size `α`

,
we must provide a smaller size `β`

, and in the case of the `succ`

, a `Nat`

of that size as well.
(Here, the size parameter `α`

is in fact an implicit size argument to the constructors;
when I want to write them explicitly I will put them in braces `{}`

,
as opposed to regular explicit size arguments, which are in brackets `[]`

.)
For instance, letting `∘`

be some arbitrary size, we have that

```
⊢ zero {∘+1} [∘] : Nat [∘+1]
⊢ succ {∘+2} [∘+1] (zero {∘+1} [∘]) : Nat [∘+2]
```

which tracks with the intuitive understanding that the construction for the natural 1 is larger
than the construction for the natural 0 (and, incidentally, the intuitive *meaning* that 0 < 1).
However, since `∘+1`

is smaller than `∘+2`

, `∘+3`

, `∘+4`

, and so on,
we can in fact give the construction for 1 a larger size:

```
⊢ succ {∘+4} [∘+1] (zero {∘+1} [∘]) : Nat [∘+4]
```

Generally, for inductive types at least, if a type has some size `s`

, then we think of it as
being syntactically *no larger* than `s`

.

Writing recursive functions on sized inductives is roughly unchanged, especially in Agda, where size arguments are often marked implicit and then inferred. Here, I’ll write all size abstractions and applications explicitly, including size parameters to constructors in braces as above.

The greatest benefit of using sized types is the ability to declare functions as *size-preserving*,
where the thing that comes out has the same size as the thing that goes in.
For instance, consider the type signature of a `monus`

function:
its output is definitely no larger than the natural we subtract from.

```
monus : ∀α β. Nat [α] → Nat [β] → Nat [α]
```

Then we can define a `div`

function using `monus`

.

```
fix div [α] [β] (n : Nat [α]) (m : Nat [β]) : Nat [α] :=
case n of
zero [γ] ⇒ zero {α} [γ]
succ [γ] k ⇒ succ {α} [γ] (div [γ] [β] (monus [γ] [β] k m) m)
```

In the case expression, we’re given a size variable `γ`

that the type system knows is smaller than
the size of the target `n`

that we’re destructing, which here is `α`

.
Then our recursive call occurs on an argument of the smaller size `γ`

.
This is why sizes denote a *relative* size difference rather than an *absolute* size:
when type checking fixpoints, we only need to ensure that recursive calls are done on something smaller,
regardless of its actual concrete size.
The typing rule for fixpoints, roughly below, describes this requirement.

```
Γ(α)(f: ∀β < α → σ[α ↦ β]) ⊢ e : σ
----------------------------------
Γ ⊢ fix f [α] : σ := e : ∀α. σ
```

Note that the first, decreasing argument of the recursive call to `div`

is not the syntatically smaller argument `k`

,
but because `monus`

preserves its size, we know that it also has the same size.
Then `div`

will pass type checking regardless of the implementation (or visibility thereof) of `monus`

.

This presentation of having bounded sizes like `∀α < s. τ`

is also known in the literature as
*inflationary fixed points* (and dually *deflationary fixed points* for coinductives).
Before the mid-2010s and before the implementation of sized types in Agda,
sized type theories commonly only had a successor operator `s+1`

,
meaning that the sized naturals would have to be defined like this:

```
data Nat : ∀α. Set where
zero : ∀α. Nat [α+1]
succ : ∀α. Nat [α] → Nat [α+1]
```

Even nonrecursive constructors like `zero`

have to have a successor size for the type system
to be logically consistent (i.e. sound).
This has carried over to the bounded-sizes presentation,
where conventionally zero also has a smaller size argument.
I’m not sure if this is strictly required for consistency.
In any case, the convention now is to use bounded sizes,
which appears to mitigate problems with pattern matching on sizes in Agda in particular.

The grammar of possible size expressions, also known as the *size algebra*,
is usually restricted to size variables and addition by constants,
so that sizes are nicely inferrable and don’t require complex solvers.
However, this does restrict the number of things we can express.
This is why most sized type theories (and Agda) also has an *infinite* size `∞`

.
Just as `Nat [s]`

represents a natural no larger than `s`

,
`Nat [∞]`

then represents *any* possible natural,
also referred to as a *full* natural, in contrast to *sized* naturals.
For instance, to even express the type signature of a `plus`

function,
we need the return type to be a full natural, since we can’t express the addition of two sizes.

```
fix plus [α] [β] (n : Nat [α]) (m : Nat [β]) : Nat [∞] :=
case n of
zero [γ] ⇒ m
succ [γ] k ⇒ succ {∞} [∞] (plus [γ] [β] k m)
```

Notice that all sizes are strictly smaller than `∞`

, *including itself*.
This is how both the size parameter and the size argument of `succ`

are `∞`

;
if not, this function wouldn’t be implementable.

This poses a problem for Agda in particular,
because we simultaneous expect `<`

to be a well-behaved strict order,
but `∞`

clearly violates this expectation.
These two simple facts yield an inconsistency,
as described by this Agda issue.
In short, the behaviour of `<`

can be encoded as an inductive type,
and well-founded induction on sizes can be defined using it.
Using `∞`

on it then brings the tower of well-ordered sizes crashing down.

There are a few proposed solutions to this problem,
most of them centered around removing the `∞ < ∞`

property of the infinite size.
This causes problems for Agda when it comes to coinductive types, but more fundamentally,
this property is really the *defining* property of what infinity is.
To remove it would be like defining a `⊥`

type without the property of being uninhabited.
On the other hand, we do want `<`

to behave intuitively like a strict order on sizes,
which is how we justify recursion on smaller sizes.
We seem to be at an impasse now, but there’s still one last question to ask ourselves:
Do we *really need* an infinite size?

Going back to full and sized naturals, given that using `∞`

appears to allow us to ignore sizes entirely,
maybe we could just used the unsized naturals from the very beginning in lieu of full naturals.
The practical problem with this is that we now need to juggle with two inductive types representing the same thing,
and more importantly, these two representations are incompatible with one another,
since we would not be able to apply an unsized natural to a function that takes a size and a sized natural of that size.

The key insight is that it’s not that an unsized natural inherently has *no* possible size to it,
but rather that it has some *unknown* size.
We can express this in the type theory using an existentially-quantified inductive type, `∃α. Nat [α]`

.
(For coindutives, the corresponding notion is simply a universally-quantified coinductive type,
although reaching this conclusion goes through a different informal argument).

To test this hypothesis, we should first be able to express our `plus`

function above using it,
directly replacing `Nat [∞]`

with `∃δ. Nat [δ]`

, constructing such a thing as a pair `⟨s, e⟩`

and destructing it by `let ⟨α, x⟩ := p in ...`

.

```
fix plus [α] [β] (n : Nat [α]) (m : Nat [β]) : ∃δ. Nat [δ] :=
case n of
zero [γ] ⇒ ⟨β, m⟩
succ [γ] k ⇒
let ⟨δ, x⟩ := plus [γ] [β] k m
in ⟨δ+1, succ {δ+1} [δ] x⟩
```

So far, so good! The resulting code is a little wordier, but intuitively type checks.
Next, to make sure that it *means* what we expect it to, supposing that we have unsized naturals,
we should be able to take an arbitrary one and transform it into an `∃α. Nat [α]`

.
Obviously such a (recursive) function would need to be syntactically guard-checked for termination.

```
fix cast (n : Nat) : ∃δ. Nat [δ] :=
case n of
zero ⇒ ⟨∘+1, zero {∘+1} [∘]⟩
succ k ⇒
let ⟨δ, x⟩ := cast k
in ⟨δ+1, succ {δ+1} [δ] x⟩
```

In the base case, we need some concrete size; we can easily add a base size ∘ to the size algebra.
The recursive case does the same thing as `plus`

, unpacking the pair and then packing it back up.
It seems like it would be easier to also add a size addition operator to the size algebra
so that `plus`

can be expressed without existential quantification,
but what about the `n`

th Fibonacci number?
What about the `n`

th factorial?
It wouldn’t be practical to allow arbitrary functions producing sizes if we want sizes to be practically inferrable,
so the existentially quantifying over sizes is a happy medium between expressivity and inferrability.

It then appears that this solves the problem of the infinite size. There’s no way to reproduce the inconsistency in Agda where an infinite size is applied to well-founded induction because infinite sizes are “actually” just unknown concrete sizes. But spoilers:

You can imagine extending this technique for circumventing the infinite size
for more inductive types than just the naturals.
However, it only works for *simple* inductive types;
when we extend to *general* inductive types,
where the recursive argument of constructors can be a *function* that returns the inductive,
it starts to break down.

As a concrete example, we’ll look at *Brouwer ordinal trees*, a general inductive type representing the ordinals.
First, we start with the inductive data definition: an ordinal is zero, a successor ordinal, or a limit ordinal.

```
data Ord [α] : Set where
Z : ∀β < α. Ord [α]
S : ∀β < α. Ord [β] → Ord [α]
L : ∀β < α. (∃α. Nat [α] → Ord [β]) → Ord [α]
```

The limit ordinal of a given function from (full) naturals to ordinals can be seen as the supremum of all the ordinals returned by that function. For instance, we can define the ordinals equivalent to the naturals by a straightforward mapping.

```
fix natToOrd [α] (n : Nat [α]) : Ord [α] :=
case n of
zero [β] ⇒ Z {α} [β]
succ [β] k ⇒ S {α} [β] (natToOrd [β] k)
```

If we were working with unsized inductives, the first limit ordinal ω would be easily defined as `L natToOrd`

.
However, we run into a problem when we attempt the same with sized inductives:

```
L {?+1} [?] (λn: ∃α. Nat [α] ⇒ let ⟨β, x⟩ := n in natToOrd [β] x)
```

First of all, what should the size that goes in the hole `?`

be?
The function argument of `L`

potentially returns a different size for each result,
rather than a fixed, common size for all of them.
Second of all, for the let expression to be well-typed,
we need to be able to project only the size out of `n`

,
which means that sizes might now involve arbitrary terms beyond the size algebra.

```
(natToOrd: ∀α. Nat [α] → Ord [α])(n: ∃α. Nat [α]) ⊢ n : ∃α. Nat [α]
(natToOrd: ∀α. Nat [α] → Ord [α])(n: ∃α. Nat [α])(β)(x : Nat [β]) ⊢ natToOrd [β] x : Ord [β]
---------------------------------------------------------------------------------------------------
(natToOrd: ∀α. Nat [α] → Ord [α])(n: ∃α. Nat [α]) ⊢ let ⟨β, x⟩ := n in natToOrd [β] x : Ord [fst n]
```

Given that ω is expressible with unsized inductives, it should also be expressible with sized inductives.
What we have is a function from naturals to ordinals, and consequently a function from full naturals to full ordinals.
What we need is some size we can pass to `L`

, as well as a function from full naturals to ordinals of that size.
In other words, we need the following function:

```
C' : (∃α. Nat [α] → ∃β. Ord [β]) → ∃β. (∃α. Nat [α] → Ord [β])
```

More generally, for some inductive type `X`

that might have a general recursive argument of the form `(a: A) → X a`

,
we need to similarly be able to bring out the existential from inside the function to outside.
(We let `ℓ`

be an arbitrary universe level, since the argument `A`

could live in any universe.)

```
C : {A: Set ℓ} → {X: ∀α. A → Set ℓ} → ((a: A) → ∃α. X [α] a) → ∃α. (a: A) → X [α] a
```

You might notice that this is in fact a form of the axiom of choice specialized to existential quantification over sizes. The general statement of the axiom is as follows:

```
AC : {A: Set ℓ} → {B: A → Set ℓ} → {X: (a: A) → B a → Set ℓ} →
((a: A) → (b : B a) × X a b) → (f: (a: A) → B a) × ((a: A) → X a (f a))
```

We could stop here and accept `C`

as a noncomputing axiom.
This would break canonicity for existential pairs, since `C`

can yield a closed neutral term that isn’t a pair.
However, if projecting the elements out of the pair is allowed, then the axiom is computational.
For the general axiom of choice, this is implemented as

```
AC g = ⟨λa: A ⇒ fst (g a), λa: A ⇒ snd (g a)⟩
```

By analogy, `C`

should be implemented as

```
C g = ⟨λa: A ⇒ fst (g a), λa: A ⇒ snd (g a)⟩
```

but this doesn’t type check: `λa: A ⇒ fst (g a)`

is a function from `A`

to a size,
whereas we expect the first argument to be merely a size.
Taking inspiration from the ordinals, we could add an operator that constructs the *limit* of a function to sizes.
That is, given a function `f`

from some `A`

to a size, we have the size expression `lim A f`

.
Then we are able to complete the implementation of `C`

.

```
C g = ⟨lim A (λa: A ⇒ fst (g a)), λa: A ⇒ snd (g a)⟩
```

Finally, we can define the limit ordinal ω, perhaps with a few more steps than desired.

```
ω : Ord [lim (∃α. Nat [α]) (λn: ∃α. Nat [α] ⇒ fst n)]
ω = let ⟨β, x⟩ := C (λn: ∃α. Nat [α] ⇒ ⟨fst n, natToOrd [fst n] (snd n)⟩)
in L [β] x
```

We now essentially have a new constructor for sizes.
This means we also have to figure out where it fits in the ordering of sizes.
By convention, we define `r < s`

to be `r+1 ≤ s`

,
and we can conclude `r+1 ≤ s+1`

if `r ≤ s`

holds.
Furthermore, `α+1 ≤ s`

holds if `α < s`

is assumed in the environment,
such as in the body of `∀α < s. τ`

.

As a limit size, `lim A f`

should be the supremum of all of the sizes returned by `f`

,
just as `L g`

is the supremum of all of the ordinals returned by `g`

.
Then firstly, being an upper bound,
if we have some size `s`

smaller than any size returned by `f`

,
it must also be smaller than `lim A f`

itself.

```
Γ ⊢ a : A
Γ ⊢ s ≤ f a
---------------
Γ ⊢ s ≤ lim A f
```

Secondly, being a *least* upper bound, if every size returned by `f`

is smaller than some `s`

,
it must be that `lim A f`

itself is also smaller than `s`

.
In other words, there cannot be a size in between the sizes from `f`

and `lim A f`

.

```
For every Γ ⊢ a : A,
Γ ⊢ f a ≤ s
--------------------
Γ ⊢ lim A f ≤ s
```

Unfortunately, this likely makes checking the size order undecidable.
For the first rule, the checker needs to somehow summon the correct `a`

out of thin air;
for the second rule, the checker needs to somehow verify the premise for *every* possible `a`

.

Given that we’ve been freely using `fst`

and `snd`

on existential size pairs,
it seems that we should promote sizes to being proper terms.
(Incidentally, in Agda they are.)
Assuming we have some type `Size`

, we can write down the typing rules for the introduction forms.
(Here, `s+1 ≡ suc s`

.)

```
Γ ⊢ s : Size
--------------
Γ ⊢ suc s : Size
Γ ⊢ A : Set ℓ
Γ ⊢ f : A → Size
------------------
Γ ⊢ lim A f : Size
```

Notice that we have an unbound universe level ℓ.
This suggests that we need to pass ℓ as an argument to either `lim`

itself or to `Size`

.
Since we’d like to treat sizes uniformly and be able to pass them around without worrying about the level,
we’ll adopt the former solution.

If we think of `Size`

as an inductive type in Agda, this forces us to put it in `Setω`

.
In other words, `Size`

in Agda would look like this:

```
open import Agda.Primitive
data Size : Setω where
suc : Size → Size
lim : {ℓ : Level} → {A : Set ℓ} → (A → Size) → Size
```

This is a problem because inductive types contain a size as a parameter,
meaning that they, too, all need to live in `Setω`

.
Take the naturals, for example: morally, they *should* be in `Set`

,
but again if defining them in Agda (and borrowing some notation for sizes), we have

```
data Nat (α : Size) : Setω where
zero : (β : Size< α) → Nat [α]
succ : (β : Size< α) → Nat [β] → Nat [α]
```

The problem would be solved if we could put `Size`

in `Set`

instead.
In Agda, this requires `Set`

to be *impredicative*, in a sense,
which when combined with large elimination of types in `Set`

in general would be inconsistent.
It’s yet unclear to me whether only allowing `Size`

to be in `Set`

as a primitive formation rule would be consistent.

```
--------------
Γ ⊢ Size : Set
```

- Modern sized types use a bounded form of universal size quantification and induce a strict order on sizes
- The conventional infinite size violates the wellfoundedness of this strict order
- An inductive with an “infinite” size is really one with
*some*size, so maybe we can replace it with existential size quantification - This works for simple inductive types, but not for general inductive types, unless:
- We add a noncomputing form of the axiom of choice, which would break canonicity; or
- We add a limit operator for sizes, which likely breaks decidability of size orders, and causes problems to do with the universe level of sizes

- Having a consistent, reasonable, and useable sized dependent type system is still an open problem

- Inductively-Defined Equality
- The J Eliminator
- The K Eliminator
- Heterogeneous Equality
- Substitution and Contractibility of Singletons
- Congruence and Coercion
- Mid-Summary
- Extensional Equality
- Function Extensionality
- Propositional Truncation/Squash Types
- Quotient Types
- Higher Inductive Types
- Cubical Type Theory
- Appendix A: Other Relevant Typing Rules
- Appendix B: Level-Heterogeneous Equality

In most modern proof assistants, the equality type and its constructor is defined as an inductive type.

```
data _≡_ {A : Type} (a : A) : A → Type where
refl : a ≡ a
```

A proof of equality (i.e. a term whose type is a propositional equality) can then be eliminated by the usual construct for deconstructing inductive data.

```
Γ ⊢ p : a ≡ {A} b
Γ (y : A) (x : a ≡ y) ⊢ P : Type
Γ ⊢ d : P[y ↦ a][x ↦ refl]
─────────────────────────────────────────────────────────
match p in _ ≡ y as x return P with
Γ ⊢ | refl ⇒ d : P[y ↦ b][x ↦ p]
end
```

In the motive `P`

, the target is bound to `x`

and the right side of the equality is bound as an index to `y`

.
Note that the left side is inferred from the type of `p`

since it is a parameter.
In a core language with only indices and no parameters, the constructor would have more arguments.

```
data Eq : (A : Type) → A → A → Type where
refl : (A : Type) → (a : A) → Eq A a a
```

This is reflected accordingly in the structure of the match expression.

```
Γ ⊢ p : Eq A a b
Γ (X : Type) (y : A) (z : A) (x : Eq X y z) ⊢ P : Type
Γ (A : Type) (a : A) ⊢ d : P[X ↦ A][y ↦ a][z ↦ a][x ↦ refl A a]
──────────────────────────────────────────────────────────────────────────
match p in Eq X y z as x return P with
Γ ⊢ | refl A a ⇒ d : P[X ↦ A][y ↦ a][z ↦ b][x ↦ p]
end
```

In a type theory without inductive data types, propositional equality can be defined in terms of formation, introduction, elimination, and computation rules.

```
Γ ⊢ a : A
Γ ⊢ b : A
──────────────── ≡-form
Γ ⊢ a ≡ b : Type
Γ ⊢ a : A
────────────────── ≡-intro
Γ ⊢ refl a : a ≡ a
Γ ⊢ p : a ≡ b
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ P : (y : A) → a ≡ y → Type
Γ ⊢ d : P a (refl a)
────────────────────────────── J-elim
Γ ⊢ J P d p : P b p
────────────────────── J-comp
Γ ⊢ J P d (refl a) ⊳ d
```

Notice that J treats the left side of the equality as a “parameter”.
An alternate formulation that doesn’t do this would type `P`

as `(x y : A) → x ≡ y → Type`

.
J can also be treated as a function rather than a construct that takes a fixed number of arguments;
in that case, its type would be:

```
J' : (A : Type) → (a b : A) →
(P : (y : A) → a ≡ y → Type) →
(d : P a (refl a)) → (p : a ≡ b) → P b p
```

*This section is adapted from the nLab article.*

Some constructs also have an η-conversion or uniqueness rule; for equality,
this resembles a computation rule where the branch is a function application and
the target need not have the canonical `refl`

form.

```
Γ ⊢ p : a ≡ b
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ P : (y : A) → a ≡ y → Type
Γ ⊢ e : (x : A) → (p : a ≡ x) → P x p
──────────────────────────────────────── J-uniq
Γ ⊢ J P (e a (refl a)) p ≈ e b p : P b p
```

(Note that this rule is mostly only useful if `e`

is a neutral form.) However, adding this rule is dangerous,
because we can now derive the following chain of conversions (below the dashed bar) under the appropriate assumptions
(above the solid bar) and definitions (between the two bars):

```
A : Type
a b : A
p : a ≡ b
────────────────────────────────
l (_ : A) (_ : a ≡ y) : A ≔ a
r (y : A) (_ : a ≡ y) : A ≔ y
P (_ : A) (_ : a ≡ y) : Type ≔ A
--------------------------------
a ≈ l b p by reduction
≈ J P (l a (refl a)) p by uniq
≈ J P a p by reduction
≈ J P (r a (refl a)) p by reduction
≈ r b p by uniq
≈ b : A by reduction
```

In short, given a propositional equality `a ≡ b`

, we are able to derive a *definitional* equality between `a`

and `b`

.
This is *equality reflection*, making the type theory extensional, and is known to cause undecidable type checking.

A complementary eliminator that we can add is the K eliminator, which eliminates equalities with definitionally equal sides. The it cannot be derived from J or the match expression, nor can it derive J.

```
Γ ⊢ p : a ≡ a
Γ ⊢ a : A
Γ ⊢ P : a ≡ a → Type
Γ ⊢ d : P (refl a)
──────────────────── K-elim
Γ ⊢ K P d p : P p
────────────────────── K-comp
Γ ⊢ K P d (refl a) ⊳ d
```

K can be used to prove that all equalities on `a`

are equal to `refl a`

(RIP),
and together they prove that all equalities of the same type are equal,
known as the *unicity* or *uniqueness of identity proofs* (UIP).
(We treat RIP as a function whose parameters are the assumptions above the solid bar.)
UIP in turn, of course, directly implies RIP.

```
A : Type
a : A
q : a ≡ a
────────────────────────────────── RIP
P (p : a ≡ a) : Type ≔ refl a ≡ p
----------------------------------
K P (refl (refl a)) q : refl a ≡ q
A : Type
a b : A
p q : a ≡ b
────────────────────────────────────────────────── UIP
P (b : A) (p : a ≡ b) : Type ≔ (q : a ≡ b) → p ≡ q
--------------------------------------------------
J P (RIP A a) p q : p ≡ q
A : Type
a : A
q : a ≡ a
────────────────────────────────── RIP'
UIP A a a (refl a) q : refl a ≡ q
```

The formation rule asserts that both sides of the equality must have the same type.
We can loosen this condition to create *heterogeneous* or *John Major* equality, as coined by Conor McBride.
The eliminator is then adjusted accordingly.
Just as for the usual homogeneous equality with J, this could also be equivalently defined as a inductive type.

```
Γ ⊢ a : A
Γ ⊢ b : B
──────────────── ≅-form
Γ ⊢ a ≅ b : Type
Γ ⊢ a : A
─────────────────── ≅-intro
Γ ⊢ refl* a : a ≅ a
Γ ⊢ p : a ≅ b
Γ ⊢ a : A
Γ ⊢ b : B
Γ ⊢ P : (Y : Type) → (y : Y) → a ≅ y → Type
Γ ⊢ d : P A a (refl* a)
─────────────────────────────────────────── J*-elim
Γ ⊢ J* P d p : P B b p
─────────────────────── J*-comp
Γ ⊢ J* P d (refl a) ⊳ d
```

Interestingly, UIP can be derived from J* alone, since the types of the equalities on both sides of RIP need no longer be the same.

```
A B : Type
a : A
b : B
q : a ≅ b
───────────────────────────────────────────────────── RIP*
P (B : Type) (b : B) (p : a ≅ b) : Type ≔ refl* a ≅ p
-----------------------------------------------------
J* P (refl* (refl* a)) q : refl* a ≅ q
A B : Type
a : A
b : B
p q : a ≅ b
────────────────────────────────────────────────── UIP*
P (b : A) (p : a ≅ b) : Type ≔ (q : a ≅ b) → p ≅ q
--------------------------------------------------
J* P (RIP* A B a b) p q : p ≅ q
```

We *cannot* derive the usual J or K from J*.
Intuitively, it seems like we should be able to prove K by substituting its motive over RIP*,
but the problem is that J*’s motive abstracts over the type while K’s doesn’t,
leading to the proof getting “stuck” at `?`

below.
We see a similar problem with trying to derive J where J’s motive also doesn’t abstract over the type.

```
A : Type
a b : A
p : a ≅ b
P : (A : Type) → A → Type
─────────────────────────────────────────────────────── subst*
Q (B : Type) (b : B) (_ : a ≅ b) : Type ≔ P A a → P B b
id (pa : P A a) : P A a ≔ pa
-------------------------------------------------------
J* Q id p : P A a → P B b
A : Type
a : A
P : a ≅ a → Type
d : P (refl* a)
p : a ≅ a
───────────────────────────────────────────────────── K?
subst* (a ≅ a) (refl* a) p (RIP* A A a a p) ? d : P p
A : Type
a b : A
P : (y : A) → a ≅ y → Type
d : P a (refl a)
p : a ≅ b
────────────────────────── J?
J* ? d p : P b p
```

*This section takes material from this discussion.*

The J eliminator can be thought of as the induction principle for equality,
where the motive depends on the equality being eliminated.
We can split the induction principle into a *recursion principle*, substitution, whose motive does not depend on the equality,
and a *uniqueness principle*, the contractibility of singletons.

The idea behind substitution is that given some equality between `a`

and `b`

, within some proposition `P`

,
we can substitute `a`

for `b`

.
As in the last section, we can derive this from the J eliminator.

```
A : Type
a b : A
P : A → Type
p : a ≡ b
──────────────────────────────────────── subst'
Q (y : A) (_ : a ≡ y) : Type ≔ P a → P y
id (pa : P a) : P a ≔ pa
----------------------------------------
J Q id p : P a → P b
```

A singleton is a type with (propositionally provably) only one inhabitant. Contractibility then states that the only proof of singletonness is reflexivity.

```
A : Type
a : A
p : (b : A) × (a ≡ b)
─────────────────────────────────────────────────── cos'
P (y : A) (q : a ≡ y) : Type ≔ ⟨a, refl a⟩ ≡ ⟨y, q⟩
---------------------------------------------------
J P (refl ⟨a, refl a⟩) (snd p) : ⟨a, refl a⟩ ≡ p
```

Alternatively, we can define these as the built-in eliminators for equality.

```
Γ ⊢ p : a ≡ b
Γ ⊢ a b : A
Γ ⊢ P : A → Type
───────────────────────── subst-elim
Γ ⊢ subst P p : P a → P b
──────────────────────────── subst-comp
Γ ⊢ subst P (refl a) pa ⊳ pa
Γ ⊢ p : (b : A) × (a ≡ b)
Γ ⊢ a : A
───────────────────────── cos-elim
Γ ⊢ cos p : ⟨a, refl a⟩ ≡ p
────────────────────────────────────── cos-comp
Γ ⊢ cos ⟨a, refl a⟩ ⊳ refl ⟨a, refl a⟩
```

*The following proof is adapted from Martin Hofmann’s dissertation, Extensional Concepts in Intensional Type Theory.*

We can derive all of the nice properties of equality from substitution and `cos`

as we do from J
(such as symmetry, transitivity, and congruence), as well as J itself.
The idea is that given `P a (refl a)`

, we can substitute across `cos ⟨a, p⟩`

to obtain a `P a p`

,
then substitute once more across `p`

to obtain `P b p`

.

```
A : Type
a b : A
P : (y : A) → a ≡ y → Type
d : P a (refl a)
p : a ≡ b
───────────────────────────────────────────────── J'
Q (y : A) : Type ≔ (p : a ≡ y) → P y p
R (y : A) × (p : a ≡ y) : Type ≔ P y p
e (p : a ≡ a) : P a p ≔ subst R (cos ⟨a, p⟩) d
-------------------------------------------------
subst Q p e p : P b p
```

Alternatively, if we have RIP, we can substitute across that to get `P a p`

from `P a (refl a)`

.

```
A : Type
a b : A
P : (y : A) → a ≡ y → Type
d : P a (refl a)
p : a ≡ b
───────────────────────────────────────────────── J'
Q (y : A) : Type ≔ (p : a ≡ y) → P y p
e (p : a ≡ a) : P a p ≔ subst (P a) (RIP A a p) d
-------------------------------------------------
subst Q p e p : P b p
```

Suppose now that we only have RIP or UIP with no K. We can then easily recover K with a single application of substitution.

```
A : Type
a : A
P : a ≡ a → Type
d : P (refl a)
p : a ≡ a
─────────────────────────── K'
subst P (RIP A a p) d : P p
```

Congruence of equality and coercion of a term along an equality of types can both be proven from substitution alone.

```
A B : Type
a b : A
f : A → B
p : a ≡ b
────────────────────────────────── cong'
P (y : A) : Type ≔ f a ≡ f y
----------------------------------
subst P p (refl (f a)) : f a ≡ f b
A B : Type
p : A ≡ B
a : A
──────────────────────── coe'
id (T : Type) : Type ≔ T
------------------------
subst id p a : B
```

On the other hand, we could define these two properties as built-in eliminators for equality. If we deal only in homogeneous equality, then the function applied in congruence must be non-dependent, but it can be dependent if we instead typed it as a heterogeneous equality.

```
Γ ⊢ p : a ≡ b
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ f : A → B
──────────────────────── cong-elim
Γ ⊢ cong f p : f a ≡ f b
Γ ⊢ p : A ≡ B
Γ ⊢ A : Type
Γ ⊢ B : Type
───────────────── coe-elim
Γ ⊢ coe p : A → B
──────────────────────────────── cong-comp
Γ ⊢ cong f (refl a) ⊳ refl (f a)
────────────────────── coe-comp
Γ ⊢ coe (refl A) a ⊳ a
```

These two, in turn, can be used to define substitution.

```
A : Type
a b : A
P : A → Type
p : a ≡ b
────────────────────────── subst'
coe (cong P p) : P a → P b
```

When using homogeneous equality, the function applied in congruence must be nondependent for both sides of the equality
to have the same type.
If we use heterogeneous equality, we can allow dependent functions.
Alternatively, since we already have the proof of equality of the elements that the function is applied over,
surely their types must be equal as well.
We can then use substitution to “fix” the type of one side of the resultant equality.
Instead of calling it dependent congruence, we’ll call it `apd`

in the HoTT tradition.

```
Γ ⊢ P : A → Type
Γ ⊢ p : a ≡ b
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ f : (x : A) → P x
───────────────────────────────────── apd-elim
Γ ⊢ apd P f p : subst P p (f a) ≡ f b
───────────────────────────────── apd-comp
Γ ⊢ apd P f (refl a) ⊳ refl (f a)
```

We can also prove `apd`

directly from J.
Since substitution and `cos`

prove J, this means that `apd`

could also be proven that way.

```
A : Type
a b : A
P : A → Type
f : (x : A) → P x
p : a ≡ b
──────────────────────────────────────────────────── apd'
Q (y : A) (p : a ≡ y) : Type ≔ subst P p (f a) ≡ f y
----------------------------------------------------
J Q (refl (f a)) p : subst P p (f a) ≡ f b
```

Notice that congruence and coercion compute only on reflexivity.
We may want to also compute congruence when `f`

is constant with respect to its argument,
making both sides of its type definitionally equal.
Similarly, we may want to also compute coercion when both sides of the type of `p`

are definitional equal,
regardless of whether `p`

itself is reflexivity or not.
(Of course, with UIP, `p`

would be propositionally equal to reflexivity.)
We can then add *regularity* rules allowing them to compute this way.
If applied to the variants of coercion and congruence that carried all of the relevant types with them,
as is the case with `cong'`

and `coe'`

, we can avoid type checking in the premises as well.

```
Γ ⊢ p : a ≡ b
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ f : A → B
Γ ⊢ f a ≈ f b
───────────────────────────────────── cong-reg
Γ ⊢ cong f p ⊳ refl (f a) : f a ≡ f b
Γ ⊢ f a ≈ f b
────────────────────────────────── cong'-reg
Γ ⊢ cong' A B a b f p ⊳ refl (f a)
Γ ⊢ p : A ≡ B
Γ ⊢ a : A
Γ ⊢ A ≈ B
─────────────────── coe-reg
Γ ⊢ coe p a ⊳ a : B
Γ ⊢ A ≈ B
─────────────────── coe'-reg
Γ ⊢ coe A B p a ⊳ a
```

If substitution is defined by coercion and congruence, then `subst P p`

on an equality `p : a ≡ b`

will also compute
when the motive `P`

is constant with respect to `a`

and `b`

.
Furthermore, J defined using substition will compute this way as well.
Note that this is orthogonal to UIP: congruence applied to an equality `p : a ≡ a`

not (yet) definitionally equal to
`refl a`

will not compute without this rule even with RIP.

Below summarizes the various relationships among J, K, substitution, and RIP/UIP. If you have the left side of the turnstile, then you may derive the right side.

```
J ⊢ subst, cos
K ⊢ RIP
RIP, J ⊢ UIP
UIP ⊢ RIP
subst, cos ⊢ J
subst, RIP ⊢ K
J* ⊢ RIP*, UIP*, subst*
J* ⊬ J, K
subst ⊢ coe, cong
coe, cong ⊢ subst
J ⊢ apd
```

Equality also satisfies the two other properties of equivalence relations: symmetry and transitivity. We prove them here with substitution, but they can be proven directly using J as well.

```
A : Type
a b : A
p : a ≡ b
────────────────────────── sym
P (y : A) : Type ≔ y ≡ a
--------------------------
subst P p (refl a) : b ≡ a
A : Type
a b c : A
p : a ≡ b
q : b ≡ c
──────────────────────── trans
P (y : A) : Type ≔ a ≡ y
------------------------
subst P q p : a ≡ c
```

*The following is also lifted from Hofmann’s Extensional Concepts in Intensional Type Theory.*

TODO: Add blurb about extensional equality

Extensional equality is characterized by the combination of two rules: equality reflection, where a propositional equality yields a definitional one, and a definitional form of UIP.

```
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ p : a ≡ b
───────────── ≡-reflect
Γ ⊢ a ≈ b : A
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ q : a ≡ b
────────────────────── ≡-RIP
Γ ⊢ refl a ≈ q : a ≡ b
```

In ≡-RIP, the type of `refl a`

correctly converts to `a ≡ b`

via reflection of `p`

itself.
Then with reflection and RIP, we can derive contractibility of singletons,
while coercion and congruence requires only reflection, and therefore the J eliminator can be derived as well.
On the other hand, if we already had the J eliminator, we can derive RIP via equality reflection.
(Thanks to @plt_amy for pointing this out.)

```
A : Type
a b : A
q : a ≡ b
───────────────────────────────────────── RIP''
P (b : A) (p : a ≡ b) : Type ≔ refl a ≡ p
-----------------------------------------
J P (refl (refl a)) q : refl a ≡ q
```

In the type of the body of `P`

, `refl a`

has type `a ≡ b`

by reflection of `p`

,
and the application of J is well-typed by reflection of `q`

.
Since J is derivable from the combination of coercion, congruence, and contractibility of singletons,
and the first two are derivable from reflection,
the missing piece is really only contractibility of singletons,
which in essence yields a form of uniqueness of identity proofs anyway.

There are often more equalities that we wish to be able to express than can be proven with just reflexivity and its eliminators. One of these is function extensionality, which equates two functions when they return the same output for each input. In other words, functions are then pointwise or observationally equal. Without extensionality, functions are only provably equal when they are implemented in definitionally equal ways.

```
Γ ⊢ f : (x : A) → B x
Γ ⊢ g : (x : A) → B x
Γ ⊢ h : (x : A) → f x ≡ g x
─────────────────────────── funext
Γ ⊢ funext f g h : f ≡ g
```

Unfortunately, there’s no satisfactory way of computing on the equality from function extensionality,
because our eliminators only compute on reflexivity.
In other words, adding function extensionality breaks *canonicity*, because the canonical proof of equality,
reflexivity, is no longer the *only* closed proof of equality.

On the other hand, we can derive function extensionality from equality reflection using η-conversion of functions.
Let `Γ = (f g : (x : A) → B x) (h : (x : A) → f x ≡ g x)`

.
The following derivation tree sketches out how a proof of `f ≡ g`

can be derived using `h`

.

```
Γ ⊢ h : (x : A) → f x ≡ g x
─────────────────────────── →-elim
Γ (x : A) ⊢ h x : f x ≡ g x
─────────────────────────── ≡-reflect
Γ (x : A) ⊢ f x ≈ g x
───────────────────────────────────────────── →-intro, →-uniq
Γ ⊢ f ≈ λ (x : A) ⇒ f x ≈ λ (x : A) ⇒ g x ≈ g
───────────────────────────────────────────── ≡-intro, conv
Γ ⊢ refl f : f ≡ g
```

The converse of function extensionality, that equal functions are pointwise equal, can easily be proven by substitution.

```
A : Type
B : A → Type
f g : (x : A) → B x
p : f ≡ g
────────────────────────────────────────────────── happly
P (g : (x : A) → B x) : Type ≔ (x : A) → f x ≡ g x
d (x : A) : f x ≡ f x ≔ refl (f x)
--------------------------------------------------
subst P p d : (x : A) → f x ≡ g x
```

Sometimes we would like to treat proofs of a certain proposition as being irrelevant so that
they are all propositionally equal.
This can be done by *truncating* or *squashing* the type and its term(s), and restricting manipulating the terms in ways that
do not allow us to distinguish among them.
Given some function `f`

from `A`

to an output type that only depends on the squashed input,
we can “lift” that function to one that takes a squashed `‖A‖`

as input instead.

```
Γ ⊢ A : Type
────────────── sq-form
Γ ⊢ ‖A‖ : Type
Γ ⊢ a : A
───────────── sq-intro
Γ ⊢ |a| : ‖A‖
Γ ⊢ a : A
Γ ⊢ b : A
──────────────────────── sq-ax
Γ ⊢ sqax a b : |a| ≡ |b|
Γ ⊢ P : ‖A‖ → Type
Γ ⊢ f : (x : A) → P |x|
Γ ⊢ p : (x y : A) → f x ≅ f y
────────────────────────────── sq-elim
Γ ⊢ unsq P p f : (x : ‖A‖) → P x
────────────────────── sq-comp
Γ ⊢ unsq P f |a| ⊳ f a
```

In addition to the usual formation, introduction, elimination, and computation rules, we also have an axiom that states that any two squashed values of the squashed type are equal. Notice that this also breaks canonicity of propositional equality.

Because the function applied in the eliminator is dependent, the condition that it acts identically on all elements
is a heterogeneous equality rather than a homogeneous one.
However, because the return type of the function can only depend on the squashed value,
and we know that the squashed values are all equal by `sqax`

, we can alternatively replace `f x ≅ f y`

by
`subst P (sqax x y) (f x) ≡ f y`

.
On the other hand, since substitution does not reduce on `sqax`

, if `P`

is nondependent, the condition does not become
`f x ≡ f y`

as we would intuitively expect, not unless we have the extra computation rule for congruence.

*This section adapts Martin Hofmann’s presentation in A simple model for quotient types.*

Instead of treating *all* terms of a type as equal, perhaps we would like to treat only *some* of them as equal.
Quotient types allow us to do so with a quotient relation `~`

: two quotiented terms are equal if they are related.
This is analogous to quotient sets, where an equivalence relation divides up the members of a set into equivalence classes.
Like with squash types, the eliminator allows “lifting” a function `f`

on `A`

to a function on the quotient space `A⧸~`

.

```
Γ ⊢ A : Type
Γ ⊢ ~ : A → A → Type
──────────────────── Q-form
Γ ⊢ A⧸~ : Type
Γ ⊢ a : A
Γ ⊢ ~ : A → A → Type
──────────────────── Q-intro
Γ ⊢ [a]˷ : A⧸~
Γ ⊢ a : A
Γ ⊢ b : A
Γ ⊢ ~ : A → A → Type
────────────────────────────────── Q-ax
Γ ⊢ Qax˷ a b : a ~ b → [a]˷ ≡ [b]˷
Γ ⊢ P : A⧸~ → Type
Γ ⊢ ~ : A → A → Type
Γ ⊢ f : (x : A) → P [x]˷
Γ ⊢ p : (x y : A) → (r : x ~ y) → f x ≅ f y
─────────────────────────────────────────── Q-elim
Γ ⊢ Qelim˷ P p f : (x : A⧸~) → P x
─────────────────────────── Q-comp
Γ ⊢ Qelim˷ P p f [a]˷ ⊳ f a
```

Also like with squash types, `Qax`

can yield a noncanonical closed proof of equality.
We can also replace `f x ≅ f y`

by `subst P (Qax˷ x y r) (f x) ≡ f y`

in the condition of the eliminator
just as was done for squash types, with the same problem of substitution not reducing on `Qax`

unless we have the extra computation rule for congruence.

*The follow proof is from Nuo Li’s Bachelor’s thesis, Quotient Types in Type Theory.*

An important property that quotient types can have is *effectiveness*:
the only elements belonging to an equivalence class of a quotiented element with respect to propositional equality
are the ones related by the quotient relation.
For a quotient to be effective, the relation must be an equivalence relation; that is,
it must be reflexive, symmetric, and transitive.
It also has to satisfy a weak form of propositional extensionality: if `x ~ z ↔ y ~ z`

, then `x ~ z ≡ y ~ z`

.
This can be derived from full propositional extensionality, which equates any two bi-implicated relations.
We stick to only the weak extensionality, which is all we need, and collect all these facts in a record type.

```
record PropEquiv (A : Type) (~ : A → A → Type) : Type where
~refl : (x : A) → x ~ x
~sym : (x y : A) → x ~ y → y ~ x
~trans : (x y z : A) → x ~ y → y ~ z → x ~ z
~ext : (x y z : A) → (y ~ z → x ~ z) → (x ~ z → y ~ z) → x ~ z ≡ y ~ z
```

With these, we can prove a lemma we will need later: if `x ~ y`

, then for any `z`

, `x ~ z ≡ y ~ z`

.

```
A : Type
~ : A → A → Type
pe : PropEquiv A ~
z x y : A
r : x ~ y
────────────────────────────────────────────────────── lemma₁
yzxz : y ~ z → x ~ z ≔ pe.~trans x y z r
xzyz : x ~ z → y ~ z ≔ pe.~trans y x z (pe.~sym x y r)
------------------------------------------------------
pe.~ext x y z yzxz xzyz : x ~ z ≡ y ~ z
```

Let `a`

be some particular `A`

we can quotient by `~`

, and let `P : A → Type`

be a function defined by `λ x ⇒ x ~ a`

.
Then we can “lift” `P`

to a function `P̂ : A⧸~ → Type`

using `Qelim˷`

, since `lemma₁`

gives us the required condition that
if `x ~ y`

then `P x ≡ P y`

when instantiated with `a`

.

Now we are ready to tackle effectiveness.
Suppose we have `p : [a]˷ ≡ [b]˷`

, where `~`

is a propositional equivalence relation.
We wish to show that `a ~ b`

.
By congruence on `p`

, using our lifted function, we have that `P̂ [a]˷ ≡ P̂ [b]˷`

, which computes to `a ~ a ≡ b ~ a`

.
Finally, by reflexivity of `~`

, coercion along the equality, and symmetry of `~`

, we obtain `a ~ b`

.
The full proof is outlined below.

```
A : Type
~ : A → A → Type
pe : PropEquiv A ~
a b : A
p : [a]˷ ≡ [b]˷
────────────────────────────────────────────────── eff
P (x : A) : Type ≔ x ~ a
Q (_ : A⧸~) : Type ≔ Type
P̂ (x : A⧸~): Type ≔ Qelim˷ Q (lemma₁ A ~ pe a) P x
lemma₂ : a ~ a ≡ b ~ a ≔ cong P̂ p
--------------------------------------------------
pe.~sym (coe lemma₂ (pe.~refl a)) : a ~ b
```

Squashes can be seen as a special case of quotients where the quotient relation is trivially true.

```
a ~ b ≔ Unit
∥A∥ ≔ A/~
|a| ≔ [a]˷
sqax a b ≔ Qax˷ a b unit
unsq P p f ≔ Qelim˷ P (λ x y _ ⇒ p x y) f
```

Higher inductive types are inductive types with quotient-like behaviour: with *equality constructors*,
you can specify new equalities between your elements.
One popular HIT is the interval, which consists of two endpoints and a path between them

```
data 𝕀 : Type where
𝟎 : 𝕀
𝟏 : 𝕀
seg : 𝟎 ≡ 𝟏
```

The eliminator for the interval requires the same kind of condition as quotient types: when eliminating an element of the interval with some function on an endpoint, the eliminator must treat both endpoints equally. On top of that, applying the eliminator to both sides of the segment should yield exactly the same proof that both endpoints are treated equally.

```
Γ ⊢ P : 𝕀 → Type
Γ ⊢ b₀ : P 𝟎
Γ ⊢ b₁ : P 𝟏
Γ ⊢ s : b₀ ≅ b₁
───────────────────────────────────── 𝕀-elim
Γ ⊢ 𝕀-elim P b₀ b₁ s : (i : 𝕀) → P i
─────────────────────────── 𝕀-comp₀
Γ ⊢ 𝕀-elim P b₀ b₁ s 𝟎 ⊳ b₀
─────────────────────────── 𝕀-comp₁
Γ ⊢ 𝕀-elim P b₀ b₁ s 𝟏 ⊳ b₁
─────────────────────────────────── 𝕀-comp-seg
Γ ⊢ apd P (𝕀-elim P b₀ b₁ s) seg ⊳ s
```

Again, use of heterogeneous equality can be replaced by a homogeneous one if we do the appropriate substitution;
`s`

would then have type `subst P seg b₀ ≡ b₁`

.

Functions on higher inductive types can also be defined by pattern matching on all constructors,
including on the equality constructors.
Just as a function `f`

defined by pattern matching on the data constructors describes how `f`

acts on each of them,
pattern matching on the equality constructors describes how applying `f`

on both sides of the equality yields an equality.
For instance, defining the interval eliminator with pattern matching below, the type of `s`

must be `𝕀-elim' 𝟎 ≅ 𝕀-elim' 𝟏`

,
or `b₀ ≅ b₁`

(or the homogeneous alternative if desired).
The application `𝕀-elim' seg`

should be thought of as a shorthand for `apd P 𝕀-elim' seg`

.

```
𝕀-elim' : (i : 𝕀) → P i
𝕀-elim' 𝟎 ≔ b₀
𝕀-elim' 𝟏 ≔ b₁
𝕀-elim' seg ≔ s
```

Curiously, just by defining the interval type, we are able to prove function extensionality.

```
A : Type
B : A → Type
f : (x : A) → B x
g : (x : A) → B x
h : (x : A) → f x ≡ g x
──────────────────────────────────────────────────────────────── funext
k (i : 𝕀) (x : A) : B x ≔ 𝕀-elim (λ _ ⇒ B x) (f x) (g x) (h x) i
----------------------------------------------------------------
cong k seg : f ≡ g
```

The resulting type is `λ (x : A) ⇒ f x ≡ λ (x : A) ⇒ g x`

by reduction of the interval eliminator,
but the uniqueness rule for functions will get us the final desired type.

Quotient types can be implemented as a higher inductive type where the equality induced by the quotient relation is an equality constructor.

```
data _⧸_ (A : Type) (~ : A → A → Type) : Type where
[_]˷ : (a : A) → A⧸~
Qax˷ : (a b : A) → a ~ b → [a]˷ ≡ [b]˷
```

The eliminator for quotients also requires that the function being defined behaves identically
on all equalities constructed by `Qax`

, with the additional information that equal elements are related.
We define by pattern matching the eliminator that corresponds to `Qelim˷ P p f [a]˷`

.

```
Q-elim' : ∀ {A ~} → (a : A⧸~) → P a
Q-elim' [a]˷ ≔ f a
Q-elim' (Qax˷ a b r) ≔ p a b r
```

*Most of this material is adapted from Naïve Cubical Type Theory
and Cubical Methods in HoTT and UF.
Please note that this section is still under construction.*

In cubical type theories, the interval is taken as a primitive pretype.
The notion of propositional equality is encoded as a *path* from an interval element into some type,
and two inhabitants of the type are equal if there is such a path between them.
Note that we allow the type of the endpoints of paths to vary along the path; in other words,
we have a *dependent* path corresponding to a *heterogeneous* equality.
Note also that the introduction form for paths, the interval abstraction, resemble functions, but are distinct from them:
`(Λi. a)`

is a path from `a[i ↦ 𝟎]`

to `a[i ↦ 𝟏]`

, whereas `(λi ⇒ a)`

is a function.
We use typed conversion and reduction so that paths applied to the interval endpoints can reduce to the path endpoints
despite not being in the canonical interval abstraction form.

```
(i : 𝕀) ∊ Γ
─────────── 𝕀-var
Γ ⊢ i : 𝕀
───────── 𝕀-𝟎
Γ ⊢ 𝟎 : 𝕀
───────── 𝕀-𝟏
Γ ⊢ 𝟏 : 𝕀
Γ ⊢ A : 𝕀 → Type
Γ ⊢ a : A 𝟎
Γ ⊢ b : A 𝟏
────────────────────── path-form
Γ ⊢ pathd A a b : Type
Γ (i : 𝕀) ⊢ a : A
────────────────────────────────────────────── path-intro
Γ ⊢ (Λi. a) : pathd (λi ⇒ A) a[i ↦ 𝟎] a[i ↦ 𝟏]
Γ ⊢ r : 𝕀
Γ ⊢ p : pathd A a b
─────────────────── path-elim
Γ ⊢ p r : A r
Γ (i : 𝕀) ⊢ a : A
──────────────────────────────────── path-end₀
Γ ⊢ (Λi. a) 𝟎 ⊳ a[i ↦ 𝟎] : A[i ↦ 𝟎]
Γ (i : 𝕀) ⊢ a : A
─────────────────────────────────── path-end₁
Γ ⊢ (Λi. a) 𝟏 ⊳ a[i ↦ 𝟏] : A[i ↦ 𝟏]
Γ ⊢ p : pathd A a b
─────────────────── path-uniq₀
Γ ⊢ p 𝟎 ⊳ a : A 𝟎
Γ ⊢ p : pathd A a b
─────────────────── path-uniq₁
Γ ⊢ p 𝟏 ⊳ b : A 𝟏
Γ (i : 𝕀) ⊢ e₁ ≈ e₂ i : A i
─────────────────────────────── path-uniq
Γ ⊢ (Λi. e₁) ≈ e₂ : pathd A a b
```

With these rules alone, we are already able to prove a few properties of equality we would expect to hold: reflexivity and (dependent, heterogeneous) congruence. Just as with the interval HIT, we can also prove function extensionality.

```
A : Type
a : A
──────────────────────────── refl*
(Λ_. a) : pathd (λ_ ⇒ A) a a
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
P : (i : 𝕀) → A i → Type
f : (i : 𝕀) → (x : A i) → P i x
p : pathd A a b
──────────────────────────────────────────────────── apd*
(Λi. f i (p i)) : pathd (λi ⇒ P i (p i)) (f a) (f b)
A : Type
B : A → Type
f : (x : A) → B x
g : (x : A) → B x
h : (x : A) → pathd (λ_ ⇒ B x) (f x) (g x)
────────────────────────────────────────────── funext'
(Λi. (h x) i) : pathd (λ_ ⇒ (x : A) → B x) f g
```

However, this is not enough: we cannot prove coercion or substitution. Since substitution can be proven from coercion and congruence, we take coercion as an additional primitive form. It takes an element of some type at some interval element and gives an element of that type at a different interval element, and reduces when the interval elements are the same. Additionally, it reduces if the type does not change between the two interval elements, similar to the regularity rule for coercions.

```
Γ ⊢ i : 𝕀
Γ ⊢ j : 𝕀
Γ ⊢ A : 𝕀 → Type
───────────────────────────── coe
Γ ⊢ coe [i ⇝ j] A : A i → A j
─────────────────────── coe-comp
Γ ⊢ coe [i ⇝ i] A a ⊳ a
Γ ⊢ A i ≈ A j
─────────────────────── coe-reg
Γ ⊢ coe [i ⇝ j] A a ⊳ a
```

Now we are able to prove some more properties: heterogeneous substitution, heterogeneous symmetry, and homogeneous transitivity.

```
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
P : (i : 𝕀) → A i → Type
p : pathd A a b
──────────────────────────────────────────── subst*
coe [𝟎 ⇝ 𝟏] (Λi. P i (p i)) : P 𝟎 a → P 𝟏 b
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
p : pathd A a b
──────────────────────────────────────────────── sym*
Q (i : 𝕀) : Type ≔ pathd (λ_ ⇒ Type) (A i) (A 𝟎)
A' (i : 𝕀) : Q i ≔ coe [𝟎 ⇝ i] Q (Λ_. A 𝟎)
P (i : 𝕀) : Type ≔ pathd (A' i) (p i) a
------------------------------------------------
coe [𝟎 ⇝ 𝟏] P (Λ_. a) : pathd (A' 𝟏) b a
A : Type
a b c : A
p : pathd (λ_ ⇒ A) a b
q : pathd (λ_ ⇒ A) b c
───────────────────────────────────────────────── trans'
P (y : A) : Type ≔ pathd (λ_ ⇒ A) a y
-------------------------------------------------
coe [𝟎 ⇝ 𝟏] (Λi. P (q i)) p : pathd (λ_ ⇒ A) a c
```

Recall that to recover the J eliminator, we need both substitution and contractibility of singletons. We can attempt to prove the contractibility, but we run into a missing piece.

```
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
p : pathd A a b
────────────────────────────────────────────────────────────────────────────────────── cos*
Q (i : 𝕀) : Type ≔ pathd (λ_ ⇒ Type) (A 𝟎) (A i)
A' (i : 𝕀) : Q i ≔ coe [𝟎 ⇝ i] Q (Λ_. A 𝟎)
--------------------------------------------------------------------------------------
Λi. ⟨p i, Λj. p (i ∧ j)⟩ : pathd (λi ⇒ (x : A i) × pathd (A' i) a x) ⟨a, Λ_. a⟩ ⟨b, p⟩
```

It appears that we need some sort of operator between interval elements, denoted `∧`

above,
that gives `𝟏`

when `i = 𝟏 = j`

, and `𝟎`

otherwise.
We can add it as a primitive operator for interval elements, called the *meet*,
as well as a similar operator `∨`

, the *join*, and the unary operator `¬`

, the *involution*.
Then the interval forms a De Morgan algebra, and this is known as *De Morgan cubical type theory*.

```
Γ ⊢ i : 𝕀
Γ ⊢ j : 𝕀
───────────── 𝕀-meet
Γ ⊢ i ∧ j : 𝕀
Γ ⊢ i : 𝕀
Γ ⊢ j : 𝕀
───────────── 𝕀-join
Γ ⊢ i ∨ j : 𝕀
Γ ⊢ i : 𝕀
────────── 𝕀-inv
Γ ⊢ ¬i : 𝕀
────────────── 𝕀-meet-comp₀ ────────────── 𝕀-join-comp₁
Γ ⊢ 𝟎 ∧ j ⊳ 𝟎 Γ ⊢ i ∨ 𝟏 ⊳ 𝟏
────────────── 𝕀-meet-comp₁ ────────────── 𝕀-join-comp₀
Γ ⊢ 𝟏 ∧ j ⊳ j Γ ⊢ i ∨ 𝟎 ⊳ i
─────────── 𝕀-inv₀ ─────────── 𝕀-inv₁
Γ ⊢ ¬𝟎 ⊳ 𝟏 Γ ⊢ ¬𝟏 ⊳ 𝟎
────────────────────── ──────────────────────
Γ ⊢ ¬(i ∧ j) ≈ ¬i ∨ ¬j Γ ⊢ ¬(i ∨ j) ≈ ¬i ∨ ¬j
```

With substitution and contractibility of singletons, we are now able to derive the (heterogeneous) J eliminator.

```
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
P : (i : 𝕀) → (y : A i) → pathd A a y → Type
d : P 𝟎 a (Λ_. a)
p : pathd A a b
───────────────────────────────────────────────────────────────────────── J*'
Q (i : 𝕀) (y : A i) : Type ≔ (p : pathd (λj ⇒ A (i ∧ j)) a y) → P i y p
R (_ : 𝕀) (y : A 𝟎) × (p : pathd (λ_ ⇒ A 𝟎) a y) : Type ≔ P 𝟎 y p
e (p : path (λ_ ⇒ A 𝟎) a a) : P 𝟎 a p ≔ subst R (cos* (λ_ ⇒ A 𝟎) a a p) d
--------------------------------------------------------------------------
subst A a b Q p e p : P 𝟏 b p
```

The presence of this additional structure also provides a simpler proof of symmetry.

```
A : 𝕀 → Type
a : A 𝟎
b : A 𝟏
p : pathd A a b
───────────────────────────────────────────────── sym*
P (i : 𝕀) : Type ≔ pathd (λj ⇒ A (i ∧ ¬j)) (p i) a
-------------------------------------------------
coe [𝟎 ⇝ 𝟏] P (Λ_. a) : pathd (λj ⇒ A ¬j) b a
```

We can also attempt to prove a heterogeneous version of transitivity.
We are given two paths, `p`

and `q`

, whose endpoints types are `A`

and `B`

, coinciding at `A 𝟏 ≈ B 𝟎`

.
However, we run into a similar but distinct problem as before.

```
A B : 𝕀 → Type
a : A 𝟎
b : A 𝟏 ≈ B 𝟎
c : B 𝟏
p : pathd A a b
q : pathd B b c
───────────────────────────────────────────────── trans*
P (i : 𝕀) : Type ≔ pathd (λj ⇒ ? A B i j) a (q i)
-------------------------------------------------
coe [𝟎 ⇝ 𝟏] P p : pathd (λj ⇒ ? A B 𝟏 j) a c
```

The missing path, `? p q i j`

, should behave as follows:

- If
`i = 𝟎`

, then return`A 𝟎`

. - If
`i = 𝟏, j = 𝟎`

, then return`A 𝟏`

, i.e.`B 𝟎`

. - If
`i = 𝟏 = j`

, then return`B 𝟏`

.

This time, it is not the interval elements that we need to somehow combine, but rather `A`

and `B`

.
To do this, we need *Kan composition*, which intuitively “closes” an open n-cube of paths.
This is beyond the scope of this post and will not be discussed.

So far, a De Morgan cubical type theory has been presented.
An alternate presentation derives the interval operators from either heterogeneous composition alone
or homogeneous composition with coercion, usually referred to as *Cartesian cubical type theory*.
See Unifying Cubical Models of Univalent Type Theory
for further details on the different kinds of cubical type theories and their connections.

Below are the typing rules for dependent functions and pairs,
and a typing rule that uses convertibility to coerce a term to a another type.
We omit the type annotation on the pair introductory form when clear from context.
We assume that `Type`

is well-behaved and causes no problems with consistency.

```
Γ ⊢ a : A
Γ ⊢ B : Type
Γ ⊢ A ≈ B
──────────── conv
Γ ⊢ a : B
Γ ⊢ A : Type
Γ (x : A) ⊢ B : Type
────────────────────── →-form
Γ ⊢ (x : A) → B : Type
Γ ⊢ A : Type
Γ (x : A) ⊢ e : B
─────────────────────────────── →-intro
Γ ⊢ λ (x : A) ⇒ e : (x : A) → B
Γ ⊢ e₁ : (x : A) → B
Γ ⊢ e₂ : A
───────────────────── →-elim
Γ ⊢ e₁ e₂ : B[x ↦ e₂]
──────────────────────────────────── →-comp
Γ ⊢ (λ (x : A) ⇒ e₁) e₂ ⊳ e₁[x ↦ e₂]
Γ (x : A) ⊢ e₁ ≈ e₂ x
─────────────────────── →-uniq
Γ ⊢ λ (x : A) ⇒ e₁ ≈ e₂
Γ ⊢ A : Type
Γ (x : A) ⊢ B : Type
────────────────────── ×-form
Γ ⊢ (x : A) × B : Type
Γ ⊢ (x : A) × B : Type
Γ ⊢ a : A
Γ ⊢ b : B[x ↦ a]
─────────────────────────────────────── ×-intro
Γ ⊢ ⟨a, b⟩ as (x : A) × B : (x : A) × B
Γ ⊢ p : (x : A) × B
─────────────────── ×-elim₁
Γ ⊢ fst p : A
Γ ⊢ p : (x : A) × B
──────────────────────── ×-elim₂
Γ ⊢ snd p : B[x ↦ fst p]
────────────────── ×-comp₁
Γ ⊢ fst ⟨a, b⟩ ⊳ a
────────────────── ×-comp₂
Γ ⊢ snd ⟨a, b⟩ ⊳ b
────────────────────── ×-uniq
Γ ⊢ ⟨fst p, snd p⟩ ≈ p
```

Convertibility (`≈`

) is defined to be the reflexive, symmetric, compatible closure of multi-step reduction (`⊳`

) and
whatever other uniqueness rules that are defined throughout.
Convertibility is generally untyped and does not rely on typing judgements and is untyped.
When convertibility is typed, the type is an input, whereas when reduction is typed, it is an output.
Then in the general convertibility rule, we check convertibility of the types as well.

```
Γ ⊢ e₁ ⊳* e : A₁
Γ ⊢ e₂ ⊳* e : A₂
Γ ⊢ A : Type
Γ ⊢ A ≈ A₁ : Type
Γ ⊢ A ≈ A₂ : Type
───────────────── ≈-⊳*
Γ ⊢ e₁ ≈ e₂ : A
```

This is a generalization of heterogeneous equality to be heterogeneous in the universe level as well.

```
Γ ⊢ ℓ₁ : Level
Γ ⊢ ℓ₂ : Level
Γ ⊢ A : Set ℓ₁
Γ ⊢ B : Set ℓ₂
Γ ⊢ a : A
Γ ⊢ b : B
───────────────────────── ≊-form
Γ ⊢ a ≊ b : Set (ℓ₁ ⊔ ℓ₂)
Γ ⊢ a : A
Γ ⊢ A : Set ℓ
Γ ⊢ ℓ : Level
────────────────── ≊-intro
Γ ⊢ refl a : a ≊ a
Γ ⊢ p : a ≊ b
Γ ⊢ a : A
Γ ⊢ b : B
Γ ⊢ A : Set ℓ₁
Γ ⊢ B : Set ℓ₂
Γ ⊢ P : (ℓ : Level) → (Y : Set ℓ) → (y : Y) → a ≊ y → Type
Γ ⊢ d : P ℓ₁ A a (refl a)
────────────────────────────────────────────────────────── H-elim
Γ ⊢ H P d p : P ℓ₂ B b p
Γ ⊢ p : a ≊ b
Γ ⊢ a : A
Γ ⊢ b : B
Γ ⊢ A B : Set ℓ
Γ ⊢ P : (Y : Set ℓ) → (y : Y) → a ≊ y → Type
Γ ⊢ d : P A a (refl a)
──────────────────────────────────────────── I-elim
Γ ⊢ I P d p : P B b p
Γ ⊢ p : a ≊ b
Γ ⊢ a b : A
Γ ⊢ P : (y : A) → a ≊ y → Type
Γ ⊢ d : P a (refl a)
────────────────────────────── J-elim
Γ ⊢ J P d p : P b p
Γ ⊢ p : a ≊ a
Γ ⊢ P : a ≊ a → Type
Γ ⊢ d : P (refl a)
──────────────────── K-elim
Γ ⊢ K P d p : P p
```