├── .gitignore ├── BuraliForti-Chains.agda ├── Hypergame.agda ├── LICENSE ├── Liar.agda ├── README.md ├── Russell-TypeIndexedSets.agda └── Yablo.agda /.gitignore: -------------------------------------------------------------------------------- 1 | *.agda~ 2 | *.agdai 3 | MAlonzo/** 4 | -------------------------------------------------------------------------------- /BuraliForti-Chains.agda: -------------------------------------------------------------------------------- 1 | {- 2 | A paradox of the Burali-Forti type, using infinite chains qua functions ℕ → X. 3 | Similar to the argument given by Per Martin-Löf for the first version of his type theory. 4 | 5 | The nomenclature is (deliberately) unusual, for didactic reasons. 6 | -} 7 | 8 | {-# OPTIONS --type-in-type #-} 9 | 10 | module BuraliForti-Chains where 11 | 12 | open import Data.Empty 13 | open import Data.Nat hiding (_⊔_) 14 | open import Agda.Primitive 15 | 16 | {- 17 | Given a set P and any binary relation ≻ between elements of P, we can define the class of ≺-chains 18 | as functions f : ℕ → P satisfying the following: 19 | * the 2nd element of the chain, f(1), is related to the 1st element, f(0), as f(1) ≺ f(0) 20 | * the 3rd element, f(2), is related to the 2nd, f(1), as f(2) ≺ f(1) 21 | * the 4th, f(3) is related to f(2), as f(3) ≺ f(2) 22 | * f(4) is related to f(3), as f(4) ≺ f(3) 23 | * f(5) ≺ f(4), 24 | * and so on... 25 | 26 | Diagrammatically, we can represent this situation as 27 | 28 | ... ≺ f(4) ≺ f(3) ≺ f(2) ≺ f(1) ≺ f(0), for indices 29 | ... > 4 > 3 > 2 > 1 > 0 30 | 31 | -} 32 | 33 | record Chain {ℓ₁ ℓ₂ : Level} {A : Set ℓ₁} (R : A → A → Set ℓ₂) : Set (ℓ₁ ⊔ ℓ₂) where 34 | field 35 | _at_ : ℕ → A 36 | is-chain : ∀ n → R (_at_ (suc n)) (_at_ n) 37 | open Chain 38 | 39 | {- 40 | We call a relation _transitive_ if whenever it relates some x to y and y to z, then it also relates x to z. 41 | 42 | The usual order relation "less than" is transitive: if x is less than y, and y is less than 43 | z, then we can safely conclude that x itself is less than z. 44 | 45 | An example of a non-transitive relation would be fatherhood: if x is the father of y, and y is the father 46 | of z, then x is usually _not_ the father of z. 47 | 48 | In what follows, we will consider a set P equipped with a transitive relation ≺. 49 | If there are no ≺-chains, then we will call that the structure (P,≺) a _django_ (since it is _unchained_). 50 | 51 | For example, the natural numbers equipped with the usual order relation < ("less than") form a django. 52 | However, the integers (positive, negative, and zero) do not form a django when equipped with the same 53 | order relation, since they contain e.g. the chain 54 | 55 | ... < -16 < -8 < -4 < -2 < -1 for indices 56 | ... > 4 > 3 > 2 > 1 > 0 57 | 58 | Exercise: convince yourself that ℕ does not contain any such chain. 59 | -} 60 | 61 | record IsDjango {ℓ₁ ℓ₂ : Level} (A : Set ℓ₁) (R : A → A → Set ℓ₂) : Set (ℓ₁ ⊔ ℓ₂) where 62 | field 63 | Django-is-transitive : ∀ {x y z} → R x y → R y z → R x z 64 | Django-is-unchained : Chain R → ⊥ 65 | 66 | record Django {ℓ₁ ℓ₂ : Level} : Set (lsuc (ℓ₁ ⊔ ℓ₂)) where 67 | field 68 | Carrier : Set ℓ₁ 69 | order : Carrier → Carrier → Set ℓ₂ 70 | is-Django : IsDjango Carrier order 71 | open IsDjango is-Django public 72 | open Django 73 | 74 | {- 75 | Given a django (P,≺), and an element t ∈ P, the "lower set" P↓t = {x ∈ P | x ≺ t} inherits the 76 | django structure: if the relation ≺ is transitive on all of P, then of course it is transitive on the 77 | subset P↓t as well. Moreover, P↓t cannot contain any ≺-chains. 78 | 79 | In our previous example, we would have ℕ↓5 = {4,3,2,1}. 80 | 81 | We call djangoes of the form (P↓t,≺) the _prefixes_ of the django (P,≺). You can think of P↓t 82 | as the structure you get from P by removing everything "above" the element t ∈ P. 83 | -} 84 | 85 | record LowerSet {ℓ₁} {ℓ₂} (P : Django {ℓ₁} {ℓ₂}) (t : Carrier P) : Set (ℓ₁ ⊔ ℓ₂) where 86 | constructor _suchThat_ 87 | field 88 | element : Carrier P 89 | proof : order P element t 90 | 91 | LowerSet-inherited-order : 92 | {ℓ₁ ℓ₂ : Level} → (P : Django {ℓ₁} {ℓ₂}) (t : Carrier P) → 93 | LowerSet P t → LowerSet P t → Set ℓ₂ 94 | LowerSet-inherited-order P t (x suchThat x-below-t) (y suchThat y-below-t) = order P x y 95 | 96 | Prefix : {ℓ₁ : Level} → (P : Django {ℓ₁} {ℓ₁}) → Carrier P → Django {ℓ₁} {ℓ₁} 97 | Prefix {ℓ₁} P t = record 98 | { Carrier = LowerSet P t 99 | ; order = LowerSet-inherited-order P t 100 | ; is-Django = record 101 | { Django-is-transitive = λ {x y z} → F(4) ---> F(3) ---> F(2) ---> F(1) ---> F(0), for 245 | ... > 4 > 3 > 2 > 1 > 0 246 | 247 | where the bₙ ∈ F(n) are bounds, and the arrows fₙ are django homomorphisms embedding the django F(n+1) 248 | into the django F(n)↓bₙ, a prefix of F(n). 249 | 250 | Since the subprefix relation is transitive, each element of my chain is in fact a subprefix of F(0), via 251 | the "collapse" homomorphism cₙ = fₙ ∘ fₙ₋₁ ∘ ... ∘ f₀ : F(n+1) → F(0). 252 | 253 | Moreover, since fₙ(bₙ₊₁) < bₙ always holds, a simple diagonalization allows us to construct the chain 254 | 255 | ... R c₃(b₄) R c₂(b₃) R c₁(b₂) R c₀(b₁) R b₀, for indices 256 | ... > 4 > 3 > 2 > 1 > 0 257 | 258 | inside F(0). But that is impossible: F(0) is a django, so it is unchained! Since we could construct a 259 | chain inside F(0) using a chain F as above, we can conclude that such chains F cannot exist. 260 | -} 261 | 262 | subpr-is-unchained : Chain _subpr_ → ⊥ 263 | subpr-is-unchained F = AllDjangoes subpr AllDjangoes subpr AllDjangoes subpr AllDjangoes, for 340 | ... > 3 > 2 > 1 > 0 341 | 342 | -} 343 | 344 | AllDjangoes-is-chained : Chain _subpr_ 345 | AllDjangoes-is-chained = record 346 | { _at_ = λ n → AllDjangoes 347 | ; is-chain = λ n → AllDjangoes-subpr-AllDjangoes 348 | } 349 | 350 | {- 351 | This contradicts the non-existence of subpr-chains established earlier. 352 | -} 353 | 354 | paradox : ⊥ 355 | paradox = Django-is-unchained AllDjangoes AllDjangoes-is-chained 356 | -------------------------------------------------------------------------------- /Hypergame.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --type-in-type #-} 2 | 3 | module Hypergame where 4 | 5 | open import Data.Empty 6 | 7 | {- 8 | We can fully describe a round of a turn-based single-player game using the following data: 9 | * the set of possible moves that we can make in the current round, and 10 | * for each possible move m, a full description of the subsequent round f(m). 11 | -} 12 | 13 | record Round : Set₁ where 14 | inductive 15 | field 16 | moves : Set 17 | subsequent-round : moves → Round 18 | open Round 19 | 20 | {- 21 | To describe a game, it suffices to fully describe its first round (as the description gives all 22 | possible first moves, and descriptions of all possible subsequent rounds). 23 | -} 24 | 25 | Game : Set₁ 26 | Game = Round 27 | 28 | {- 29 | We call a game G finite if either 30 | * G has finished, i.e. we cannot make any valid moves, or else 31 | * no matter which valid move we make in the current round, the game we end up playing in the next round 32 | is itself a finite game. 33 | 34 | Plainly speaking, a game is finite if it ends after finitely many rounds, no matter what sequence of 35 | moves is made by the player. 36 | 37 | Notice that a finite game may have infinitely many possible moves, and it may even have arbitrarily 38 | long finite sequences of moves (consider for example the game N where you first pick a natural number, 39 | then you have to pick a number that is smaller than your previous one, and so on until you eventually 40 | reach 0. 41 | -} 42 | 43 | data IsFinite (G : Game) : Set where 44 | game-is-over : (moves G → ⊥) → IsFinite G 45 | all-subsequent-rounds-are-finite : (∀ (m : moves G) → IsFinite (subsequent-round G m)) → IsFinite G 46 | 47 | record FiniteGame : Set₁ where 48 | field 49 | playGame : Game 50 | isFinite : IsFinite playGame 51 | open FiniteGame 52 | 53 | {- 54 | The Hypergame has the following rules: 55 | 1. In the first round of the hypergame, you can choose any finite game G. 56 | 2. In the subsequent rounds, play proceeds as if you were playing the game G that you picked in the 57 | first round. The Hypergame concludes once G is over. 58 | 59 | Defining Hypergame would run into size issues if we didn't enable `--type-in-type`. 60 | -} 61 | 62 | Hypergame : Round 63 | Hypergame = record { moves = FiniteGame ; subsequent-round = λ fg → playGame fg } 64 | 65 | {- 66 | The Hypergame is a finite game, since no matter what move you make in the first round, the game that 67 | you end up playing in the subsequent rounds is itself finite. 68 | -} 69 | 70 | isFinite-Hypergame : IsFinite Hypergame 71 | isFinite-Hypergame = all-subsequent-rounds-are-finite isFinite 72 | 73 | finite-Hypergame : FiniteGame 74 | finite-Hypergame = record { playGame = Hypergame ; isFinite = isFinite-Hypergame } 75 | 76 | {- 77 | But now consider the following strategy: 78 | 1. In the first round of Hypergame, I have to pick a finite game G to play. We've just proved that 79 | Hypergame is a finite game , so I can pick G as Hypergame itself. 80 | 2. On the next round, I'm playing Hypergame again, so I have to pick a finite game G to play. 81 | I pick Hypergame again. 82 | 3. I continue picking Hypergame in every round... 83 | 84 | This sequence of moves is infinite. Hence Hypergame is not a finite game after all! 85 | -} 86 | 87 | isInfinite-Hypergame : IsFinite Hypergame → ⊥ 88 | isInfinite-Hypergame (game-is-over x) = x finite-Hypergame 89 | isInfinite-Hypergame (all-subsequent-rounds-are-finite x) = isInfinite-Hypergame (x finite-Hypergame) 90 | 91 | {- 92 | We have established that Hypergame is finite, and then that Hypergame is not finite, a contradiction. 93 | -} 94 | 95 | paradox : ⊥ 96 | paradox = isInfinite-Hypergame isFinite-Hypergame 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Zoltan A. Kocsis 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Liar.agda: -------------------------------------------------------------------------------- 1 | {- 2 | The liar paradox, showing that the positivity check is required to maintain consistency 3 | in the presence of inductive types. 4 | -} 5 | 6 | {-# OPTIONS --no-positivity-check #-} 7 | 8 | module Liar where 9 | 10 | open import Data.Empty 11 | 12 | {- 13 | The liar sentence says "the Liar sentence is false". 14 | -} 15 | 16 | record Liar : Set where 17 | inductive 18 | field 19 | Liar-fails : Liar → ⊥ 20 | open Liar 21 | 22 | {- 23 | Assume that the liar sentence holds. It then fails, a contradiction. Therefore, our assumption 24 | must have been faulty, and the liar sentence does not hold. 25 | -} 26 | 27 | not-liar : Liar → ⊥ 28 | not-liar liar = Liar-fails liar liar 29 | 30 | {- 31 | We just proved that the liar sentence fails. But it says precisely this, so it must hold. 32 | -} 33 | 34 | liar : Liar 35 | liar = record { Liar-fails = not-liar } 36 | 37 | {- 38 | We managed to prove that the liar sentence both holds and fails, a contradiction. 39 | -} 40 | 41 | paradox : ⊥ 42 | paradox = not-liar liar 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # typical-antiphrasis 2 | 3 | Here we collect and categorize logical paradoxes (proofs of falsum, *antinomies*) affecting variants of (Martin-Löf-style) type theory. 4 | 5 | We aim to provide uniform, reasonably self-contained and didactically sound presentations of every known paradox, presented (when possible) as commented scripts in the language of the [Agda](https://agda.readthedocs.io/en/v2.6.0.1/getting-started/what-is-agda.html) proof assistant. 6 | 7 | We hope that the repository will serve as both a learning resource for those who wish to improve their understanding of logical paradoxes and their proofs in inconsistent type theories, as well as a reference for researchers in type theory who need to keep track of potential inconsistencies and *explosive* interactions between features. 8 | 9 | ## Usage 10 | 11 | You can read the proofs and explanations as ordinary UTF-8 text files (e.g. via Github's built-in viewer). Type-checking the proofs requires a fairly recent version of Agda (2.6.0.1 should suffice) and [its standard library](https://github.com/agda/agda-stdlib/releases/tag/v1.3). 12 | 13 | ## Table of Contents 14 | 15 | * [BuraliForti-Chains.agda](BuraliForti-Chains.agda): The straightforward version of the Burali-Forti paradox (*does the set of all well-ordered sets admit a well-ordering?*) which defines descending chains explicitly using natural numbers. Requires: `--type-in-type`, sigma types, natural numbers. 16 | * [Hypergame.agda](Hypergame.agda): The hypergame paradox (*is the game where you can choose to play any finite game itself finite?*; provenance unknown), which one may regard as a variant of the Burali-Forti paradox. Requires: `--type-in-type`, inductive types. 17 | * [Liar.agda](Liar.agda): A version of the Liar paradox (*if I claim I'm lying, am I telling the truth?*) shows that the types of the constructors of an inductive data type may only occur strictly positively in the types of their arguments, on pain of inconsistency. Requires: `--no-positivity-check`, inductive types. 18 | * [Russell-TypeIndexedSets.agda](Russell-TypeIndexedSets.agda): A version of Russell's paradox (*does the set of all sets that do not contain themselves contain itself?*) that uses (inductively defined) type-indexed sets to obtain an analogue of the set-theoretic membership relation. Requires: `--type-in-type`, inductive types. 19 | * [Yablo.agda](Yablo.agda): Yablo's paradox (*if each Cretan asserts that all other Cretans are liars, is any one of them telling the truth?*) is a variant of the Liar paradox which demonstrates that positivity requirements cannot be relaxed even for parametrized (as opposed to indexed) types. Requires: `--no-positivity-check`, inductive types. 20 | 21 | ## Contributing 22 | 23 | 1. Create a fork! 24 | 2. Create your feature branch: `git checkout -b my-new-feature` 25 | 3. Commit your changes: `git commit -am 'Add some feature'` 26 | 4. Push to the branch: `git push origin my-new-feature` 27 | 5. Submit a pull request. 28 | 29 | This repository was created by merging many older ones (including some [very old ones](https://github.com/zaklogician/YablosParadox/tree/gh-pages)), written in multiple different styles. Contributions that fix style issues/irregularities are very welcome. 30 | -------------------------------------------------------------------------------- /Russell-TypeIndexedSets.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --type-in-type #-} 2 | 3 | module Russell-TypeIndexedSets where 4 | 5 | open import Agda.Primitive 6 | open import Data.Empty 7 | open import Data.Product 8 | open import Relation.Binary.PropositionalEquality 9 | 10 | {- 11 | Russell’s paradox, the most well-known of the logical paradoxes, highlighted the inconsistency of the 12 | set theory of Cantor and Frege. The ordinary formulation of Russell's paradox requires that sets 13 | have a membership relation _∈_ defined over them. At first it may seem that such a relation has no 14 | straightforward analogue in type theory. However, inductive types allow us to define "type-indexed sets", 15 | whose behavior closely resembles that of sets in "pure" set theories (such as the naive set theory of 16 | Cantor and Frege, and even Zermelo-Fraenkel Set Theory). 17 | 18 | A type-indexed set (TIS) consists of an indexing type I, and a type-indexed set f(x) for each x : I. 19 | We can regard the type-indexed sets that belong to the range of the function f as the elements of the 20 | type-indexed set. 21 | -} 22 | 23 | record TIS : Set₁ where 24 | inductive 25 | constructor tis 26 | field 27 | IndexType : Set 28 | elements : IndexType → TIS 29 | open TIS 30 | 31 | {- 32 | We obtain a membership relation (_∈_) that relates type-indexed sets to other type-indexed sets. 33 | -} 34 | 35 | _∈_ : TIS → TIS → Set₁ 36 | x ∈ y = ∃ λ i → elements y i ≡ x 37 | 38 | {- 39 | Enabling `--type-in-type` allows us to define a comprehension principle, analogous to the unrestricted 40 | comprehension principle of Cantor-Frege-style naive set theory. 41 | 42 | Given a property φ that a type-indexed set may have, we can consider the type `Σ(x ∈ TIS).φ(x)`. 43 | Recall that this type consists of pairs (x,p) where x is some type-indexed set, and `p` constitutes a 44 | proof that x satisfies the property φ. Equipping this type with the obivous projection function of 45 | signature `(Σ(x ∈ TIS).φ(x)) → TIS` yields a type-indexed set whose members satisfy the property φ. 46 | We write ⟦φ⟧ to denote this type-indexed set. 47 | -} 48 | 49 | ⟦_⟧ : (TIS → Set) → TIS 50 | ⟦ φ ⟧ = tis (∃ λ (x : TIS) → φ x) proj₁ 51 | 52 | {- 53 | The Russell TIS contains precisely those type-indexed sets that do not contain themselves as elements. 54 | So elements of R do not contain themselves, and type-indexed sets that do not contain themselves always 55 | belong to R. 56 | -} 57 | 58 | R : TIS 59 | R = ⟦ (λ x → x ∈ x → ⊥) ⟧ 60 | 61 | element-of-R-does-not-contain-itself : ∀ x → x ∈ R → x ∈ x → ⊥ 62 | element-of-R-does-not-contain-itself x ((.x , k-notin-k) , refl) = k-notin-k 63 | 64 | does-not-contain-itself-belongs-to-R : ∀ x → (x ∈ x → ⊥) → x ∈ R 65 | does-not-contain-itself-belongs-to-R x x-notin-x = (x , x-notin-x) , refl 66 | 67 | {- 68 | Now assume that the TIS R contains itself. Since elements of R do not contain themselves, and R ∈ R 69 | by assumption, we conclude that R does not contain itself, a contradiction. Our assumption must have 70 | been faulty, so we conclude that R does not contain itself. 71 | -} 72 | 73 | R-notin-R : R ∈ R → ⊥ 74 | R-notin-R R-in-R = element-of-R-does-not-contain-itself R R-in-R R-in-R 75 | 76 | {- 77 | Since R does not contain itself, it must belong to R, a contradiction. 78 | -} 79 | 80 | R-in-R : R ∈ R 81 | R-in-R = does-not-contain-itself-belongs-to-R R R-notin-R 82 | 83 | paradox : ⊥ 84 | paradox = R-notin-R R-in-R 85 | -------------------------------------------------------------------------------- /Yablo.agda: -------------------------------------------------------------------------------- 1 | {- 2 | A Yabloesque paradox, showing that the positivity check is required to maintain consistency 3 | in the presence of inductive types, and it cannot be weakened for parametric families. 4 | -} 5 | 6 | {-# OPTIONS --no-positivity-check #-} 7 | 8 | module Yablo where 9 | 10 | open import Data.Nat 11 | open import Data.Empty 12 | 13 | {- 14 | Consider a natural number n. The nth Yablo sentence says that the (n+1)st, (n+2)nd, (n+3)rd and so 15 | on Yablo sentences are all false. 16 | -} 17 | 18 | record Yablo (n : ℕ) : Set where 19 | inductive 20 | field 21 | subsequent-Yablo-false : ∀ k → n < k → Yablo k → ⊥ 22 | open Yablo 23 | 24 | {- 25 | If the nth Yablo sentence holds, then all subsequent ones fail. In particular, the (n+2)nd, (n+3)rd, 26 | (n+4)th and so on Yablo sentences all fail. But the (n+1)st Yablo sentence says precisely that these 27 | all fail, so the (n+1)st Yablo sentence must hold. 28 | -} 29 | 30 | Yablo-n-implies-Yablo-n+1 : ∀ n → Yablo n → Yablo (suc n) 31 | Yablo-n-implies-Yablo-n+1 n yablo-n = 32 | record { 33 | subsequent-Yablo-false = λ k sn