Realising level polymorphic subsets within records - set

Using the notion of subsets as predicates,
ℙ : ∀ {b a} → Set a → Set (a ⊔ suc b)
ℙ {b} {a} X = X → Set b
I'd like to consider structures endowed with a predicate on subsets,
record SetWithAPredicate {a c} : Set {!!} where
field
S : Set a
P : ∀ {b} → ℙ {b} S → Set c
This is an ill-formed construction due to the level quantification used in ℙ. Everything works fine when I use S, P as parameters to a module, but I'd like them to be records so that I can form constructions on them and give instances of them.
I've tried a few other things, such as moving the level b of ℙ inside the definition via an existential but then that led to metavaraible trouble. I also tried changing the type of P,
P : ℙ {a} S → Set c
but then I can no longer ask for, say, the empty set to have the property:
P-⊥ : P(λ _ → ⊥)
This is not well typed since Set != Set a ---I must admit, I tried to use Level.lift here, but failed to do so.
More generally, this will also not allow me to express closure properties, such as P is closed under arbitrary unions ---this is what I'm really interested in.
I understand that I can just avoid level polymorphism,
ℙ' : ∀ {a} → Set a → Set (suc zero ⊔ a)
ℙ' {a} X = X → Set
but then simple items such as the largest subset,
ℙ'-⊤ : ∀ {i} {A : Set i} → ℙ' A
ℙ'-⊤ {i} {A} = λ e → Σ a ∶ A • a ≡ e
-- Σ_∶_•_ is just syntax for Σ A (λ a → ...)
will not even typecheck!
Perhaps I did not realise the notion of subset as predicate appropriately ---any advice would be appreciated. Thank-you!

You need to lift b out from P like this
record SetWithAPredicate {a c} b : Set {!!} where
field
S : Set a
P : ℙ {b} S → Set c
Yes, this is ugly and annoying, but that's how it's done in Agda (an example from standard library: _>>=_ is not properly universe polymorphic). Lift can help sometimes, but it quickly gets out of hand.
Perhaps I did not realise the notion of subset as predicate
appropriately ---any advice would be appreciated.
Your definition is correct, but there is another one, see 4.8.3 in Conor McBride's lecture notes.

Related

What are the rules for custom syntax declarations in Agda?

The Agda docs don't really have much to say on syntax declarations, and a cursory glance at the source code is less than illuminating, so I've been trying to piece it together myself using examples from the standard library like Σ[_]_ and ∃[_]_. I can reproduce an (admittedly rather contrived) example like theirs fairly easily
twice : {A : Set} → (A → A) → A → A
twice f x = f (f x)
syntax twice (λ x → body) = twice[ x ] body
But when I try to define custom syntax that binds two variables, I get an error
swap : {A B C : Set} → (A → B → C) → B → A → C
swap f y x = f x y
syntax swap (λ x y → body) = swap[ x , y ] body
Specifically,
Parse error
y<ERROR>
→ body) = swap[ x , y ] body
...
So I assume there are some rules as to what's allowed on the left-hand side of a syntax declaration. What are these rules, and what of them prohibits my two-variable lambda form above?
Currently Agda does not allow syntax declarations with multi-argument lambda abstractions. This is a known limitation, see the issue tracker for the corresponding enhancement request.

How to define an empty set with axiom of subsets in coq

I have an axiom
Parameter set : Type.
Parameter IN : set->set->Prop.
Axiom AXIOM_OF_SUBSETS :
forall prop x, exists y, forall u,
IN u y <-> IN u x /\ (prop u)
.
Now I would like to build an empty set out of this, like
Definition EMPTYSET : set.
Check (AXIOM_OF_SUBSETS (fun _ : set => False) x).
The result of Check is:
AXIOM_OF_SUBSETS (fun _ : set => False) x
: exists y : set,
forall u : set, IN u y <-> IN u x /\ False
Is there a way to define an EMPTYSET in this situation?
I have found a very simple, but dangerous solution for this:
Just change Parameter set : Type. to Parameter set : Prop..
It worked well at least for axioms, lemmas and theorems that I have written so far.
Will this be the right way to resolve the issue for the rest of the program?
For the problem right above, refer to the https://github.com/coq/coq/wiki/Prop_or_Set .
I take it that you want to formalize Zermelo-Fraenkel set theory in Coq. There are two issues with your code:
In order to apply your axiom, you need to have some set lying around. (Your code mentions a variable x that is not defined anywhere.) One popular option is to combine the axiom of subsets with another axiom that guarantees the existence of some set, such as the axiom of infinity. If you go this way, you need to declare this axiom explicitly.
Coq does not allow the axiom of choice by default. As a result, it is not possible to extract a witness of an existence proof, and to define EMPTYSET based on the proof term you gave. You can solve this issue by either assuming the axiom of choice (check singleton_choice in Coq.Logic.ClassicalChoice (https://coq.github.io/doc/master/stdlib/Coq.Logic.ClassicalChoice.html)), or by slightly changing your formulation of your axiom to avoid the existential quantifier.
Axiom set : Type.
Axiom In : set -> set -> Prop.
Axiom comprehension : (set -> Prop) -> set -> set.
Axiom comprehension_spec :
forall prop x u, In u (comprehension prop x) <-> In u x /\ prop u.

Is this formalization of the empty set correct in Agda?

I'm following The Haskell Road to Logic, Maths and Programming in Agda.
The book states:
The empty set is trivially a relation and is the smallest relation between two sets A and B
in Agda:
data ∅ : Set where
record ⊤ : Set where
record Σ (A : Set) (B : A → Set) : Set₁ where
constructor _,_
field
π₁ : A
π₂ : B π₁
_×_ : Set → Set → Set₁
A × B = Σ A (λ _ → B)
infixr 5 _×_ _,_
Relation : Set → Set₁
Relation P = P × P → Set
With that, I can define relations on specific sets:
lteℕ : Relation ℕ
lteℕ(x , y) = x ≤ℕ y where
_≤ℕ_ : ℕ → ℕ → Set
O ≤ℕ O = ⊤
O ≤ℕ S y = ⊤
S x ≤ℕ O = ∅
S x ≤ℕ S y = x ≤ℕ y
infixr 5 _≤ℕ_
But now I have a problem, because the signature for the empty set relation:
cannot be the empty set, since I already defined it as the unhabited type previously
results in the error Set₁ != Set when checking that the expression Set has type Set even when defined with a distinct symbol as Ø : Relation Set due to the necessity to avoid Russell's paradox in the language.
Is there a way around that that is still logically consistent? Thanks!
The answer depends on what you call a set. If by set you mean a representation of the mathematical sets, such as a list, then the empty set is just represented by the empty list.
If by set you mean the Agda Set which means a type, then the answer is a bit more complicated: there is not an empty type, but there are as many as you can think of. More precisely, there are as many empty types as data types for which you don't provide any constructor. The question is then more "which of these types do I chose to model the empty set ?" rather than "how do I model the empty set ?".
Here is an example of an agda module which emphasizes this aspect: First, I have a few imports and the header of my module:
open import Agda.Primitive
open import Data.Nat hiding (_⊔_)
module EmptySets where
Then I start by an empty type, the more simple you can think of:
data Empty : Set where
From this data type, it is possible to write an eliminator:
Empty-elim : ∀ {a} {A : Set a} → Empty → A
Empty-elim ()
This basically says that anything holds if Empty holds.
But, I could have also chosen to represent the empty set as the empty relation by defining a family of types, all empty, which are all relations. First, relations needs to be defined (I took the definition from the standard library):
REL : ∀ {a b} → Set a → Set b → (ℓ : Level) → Set (a ⊔ b ⊔ lsuc ℓ)
REL A B ℓ = A → B → Set ℓ
Then the family of empty relations can be defined :
data EmptyRelation {a b ℓ} {A : Set a} {B : Set b} : REL A B ℓ where
Since all these types are empty, they all provide an eliminator as well:
EmptyRelation-elim : ∀ {a b x ℓ} {A : Set a} {B : Set b} {X : Set x} {u : A} {v : B} → EmptyRelation {ℓ = ℓ} u v → X
EmptyRelation-elim ()
And, as a consequence, it is possible to instantiate this generic type to get a specific empty type, for instance, the empty relation over natural numbers, which never holds:
EmptyNaturalRelation : REL ℕ ℕ lzero
EmptyNaturalRelation = EmptyRelation
This is what is explained in the book: since a relation is a set of pairs, then the empty type is the smallest of this relation: the one where there are no pairs in it.
But you could also use predicates instead of relations, saying that the empty set is the smallest predicate over a given type: the one that never holds, in which case this is represented as the following:
Pred : ∀ {a} → Set a → (ℓ : Level) → Set (a ⊔ lsuc ℓ)
Pred A ℓ = A → Set ℓ
data EmptyPredicate {a ℓ} {A : Set a} : Pred A ℓ where
And you could be even crazier and decide to model the empty set as the following:
data EmptySomething {a} {A B C D E Z : Set a} : A → B → C → D → E → Z → Set where
All in all, there are no empty set in agda, but there are a potential infinity of empty types.
As for the code you presented in your question, there are several inaccuracies:
The relations are usually defined on two arguments instead of pairs of argument, which you can then curry on if needed to make them take a pair as parameter.
Why would you make lteℕ depend on _≤ℕ_ and not define it directly ?
You should define lteℕ as a data type rather than a function which returns either bottom or top, which will allow you to case-split on such a term in the future. Usually, this is defined this way (in the standard library):
data _≤_ : Rel ℕ 0ℓ where
z≤n : ∀ {n} → zero ≤ n
s≤s : ∀ {m n} (m≤n : m ≤ n) → suc m ≤ suc n

Law of excluded middle in Agda

I've heard the claim that Agda's Martin-Lof Type Theory with Excluded Middle is consistent. How would I go about adding it as a postulate? Also, after Adding LEM, is it then classical first-order logic? By this I mean, do I also have the not (for all) = there exist (not) equivalence? I don't know type theory, so please add additional explanation if you quote any results in type theory.
In MLTT, exists corresponds to a dependent pair which is defined in Data.Product in the standard library. It packages together the existence witness and the proof that it has the right property.
It is not necessary to postulate anything to prove that the negation of an existential statement implies the universal statement of the negated property:
∄⇒∀ : {A : Set} {B : A → Set} →
¬ (∃ λ a → B a) →
∀ a → ¬ (B a)
∄⇒∀ ¬∃ a b = ¬∃ (a , b)
To prove the converse however you do need the law of excluded middle to have a witness appear out of thin air. It is really easy to extend Agda with new postulates, you can simply write (Dec is defined in Relation.Nullary):
postulate LEM : (A : Set) → Dec A
It's always a good thing to remember how to prove double-negation elimination starting from LEM and we will need later on anyway so there it is (case_of_ is defined in Function and explained in README.Case):
¬¬A⇒A : {A : Set} → ¬ (¬ A) → A
¬¬A⇒A {A} ¬¬p =
case LEM A of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬¬p ¬p
}
And you can then prove that the negation of a universal statement implies an
existential one like so:
¬∀⇒∃ : {A : Set} {B : A → Set} →
¬ (∀ a → B a) →
∃ λ a → ¬ (B a)
¬∀⇒∃ {A} {B} ¬∀ =
case LEM (∃ λ a → ¬ B a) of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬∀ (¬¬A⇒A ∘ ∄⇒∀ ¬p)
}
A gist with all the right imports

Understanding the syntax of Agda

Using the following as an example
postulate DNE : {A : Set} → ¬ (¬ A) → A
data ∨ (A B : Set) : Set where
inl : A → A ∨ B
inr : B → A ∨ B
-- Use double negation to prove exclude middle
classical-2 : {A : Set} → A ∨ ¬ A
classical-2 = λ {A} → DNE (λ z → z (inr (λ x → z (inl x)))
I know this is correct, purely because of how agda works, but I am new to this language and can't get my head around how its syntax works, I would appreciate if anyone can walk me through what is going on, thanks :)
I have experience in haskell, although that was around a year ago.
Let's start with the postulate. The syntax is simply:
postulate name : type
This asserts that there exists some value of type type called name. Think of it as axioms in logic - things that are defined to be true and are not be questioned (by Agda, in this case).
Next up is the data definition. There's a slight oversight with the mixfix declaration so I'll fix it and explain what it does. The first line:
data _∨_ (A B : Set) : Set where
Introduces a new type (constructor) called _∨_. _∨_ takes two arguments of type Set and then returns a Set.
I'll compare it with Haskell. The A and B are more or less equivalent to a and b in the following example:
data Or a b = Inl a | Inr b
This means that the data definition defines a polymorphic type (a template or a generic, if you will). Set is the Agda equivalent of Haskell's *.
What's up with the underscores? Agda allows you to define arbitrary operators (prefix, postfix, infix... usually just called by a single name - mixfix). The underscores just tell Agda where the arguments are. This is best seen with prefix/postfix operators:
-_ : Integer → Integer -- unary minus
- n = 0 - n
_++ : Integer → Integer -- postfix increment
x ++ = x + 1
You can even create crazy operators such as:
if_then_else_ : ...
Next part is definition of the data constructors itself. If you've seen Haskell's GADTs, this is more or less the same thing. If you haven't:
When you define a constructor in Haskell, say Inr above, you just specify the type of the arguments and Haskell figures out the type of the whole thing, that is Inr :: b -> Or a b. When you write GADTs or define data types in Agda, you need to specify the whole type (and there are good reasons for this, but I won't get into that now).
So, the data definition specifies two constructors, inl of type A → A ∨ B and inr of type B → A ∨ B.
Now comes the fun part: first line of classical-2 is a simple type declaration. What's up with the Set thing? When you write polymorphic functions in Haskell, you just use lower case letters to represent type variables, say:
id :: a -> a
What you really mean is:
id :: forall a. a -> a
And what you really mean is:
id :: forall (a :: *). a -> a
I.e. it's not just any kind of a, but that a is a type. Agda makes you do this extra step and declare this quantification explicitly (that's because you can quantify over more things than just types).
And the curly braces? Let me use the Haskell example above again. When you use the id function somewhere, say id 5, you don't need to specify that a = Integer.
If you used normal paretheses, you'd have to provide the actual type A everytime you called classical-2. However, most of the time, the type can be deduced from the context (much like the id 5 example above), so for those cases, you can "hide" the argument. Agda then tries to fill that in automatically - and if it cannot, it complains.
And for the last line: λ x → y is the Agda way of saying \x -> y. That should explain most of the line, the only thing that remains are the curly braces yet again. I'm fairly sure that you can omit them here, but anyways: hidden arguments do what they say - they hide. So when you define a function from {A} to B, you just provide something of type B (because {A} is hidden). In some cases, you need to know the value of the hidden argument and that's what this special kind of lambda does: λ {A} → allows you to access the hidden A!

Resources