Zulip Chat Archive
Stream: new members
Topic: Existential quantifier and Sigma type
Martin Dvořák (Dec 09 2021 at 16:37):
I am confused about existential quantifiers and Sigma types.
constant α : Type
constant p : α -> Prop
#check Π x : α, p x
#check ∀ x : α, p x
#check Σ x : α, p x
#check ∃ x : α, p x
Why is Σ x
syntactically incorrect whereäs both Π x
and ∀ x
are syntactically correct (and mean the same thing)? Isn't ∀
just a syntactic sugar for Π
in the same way that ∃
is, at least I supposed, a syntactic sugar for Σ
under the assumption that p x : Prop
?
Reid Barton (Dec 09 2021 at 16:42):
(First, all of these are syntactically correct.)
∀
and Π
are indeed the same, but ∃
and Σ
are completely separate: the first is docs#Exists and the second is docs#sigma.
Martin Dvořák (Dec 09 2021 at 16:43):
Oh, sorry, I considered type mismatch to be a kind of syntactic error.
Martin Dvořák (Dec 09 2021 at 16:50):
How can I find a similar documentation for Pi instead of Sigma?
Chris B (Dec 09 2021 at 16:53):
Pi is a primitive. There's some info on it in section 4.1 of TPIL.
Martin Dvořák (Dec 09 2021 at 16:58):
What is the difference between Pi being primitive and Sigma not being primitive? Does Pi have a constructor (as a structure) as well?
Chris B (Dec 09 2021 at 17:05):
No, it doesn't have a constructor. Pi/forall is a kind of expression that the kernel handles directly because it's 'part of the system'. Sigma is an inductive type that gets declared by users.
Martin Dvořák (Dec 09 2021 at 17:06):
Oh, thank you!
Martin Dvořák (Dec 09 2021 at 17:09):
This leaves me with the last question: Why cannot ∃
be translated to Σ
in the similar way how ∀
is translated to Π
(or maybe not translated to the other symbol but both being translated to the same kernel expression)?
Eric Wieser (Dec 09 2021 at 17:10):
∀
only exists in the pretty printer and as notation (for Π a, p a
when p a : Prop
), there's no real translation happening. docs#sigma and docs#Exists are different types.
Martin Dvořák (Dec 09 2021 at 17:11):
Yes, thanks, but why do they need to be different types?
Eric Wieser (Dec 09 2021 at 17:11):
Because they reside in different universes
Eric Wieser (Dec 09 2021 at 17:12):
Respectively, sigma p : Type (max u v)
, psigma p : Sort (max 1 u v)
, Exists p : Prop
Eric Wieser (Dec 09 2021 at 17:13):
arguably we don't need both sigma
and psigma
, beyond the fact that Sort (max 1 u v)
isannoying vs Type (max u v)
Martin Dvořák (Dec 09 2021 at 17:14):
I can now see that
constant α : Type
constant p : α -> Type 3
#check ∀ x : α, p x
is also correct.
Martin Dvořák (Dec 09 2021 at 17:17):
Eric Wieser said:
Because they reside in different universes
But why can Π x : α
eat p : α -> Sort 0
which Σ x : α
rejects?
Eric Wieser (Dec 09 2021 at 17:18):
sigma
rejects that because it's defined to reject that
Eric Wieser (Dec 09 2021 at 17:18):
psigma
, Σ' x, p x
doesn't, but is more annoying to work with
Martin Dvořák (Dec 09 2021 at 17:18):
Yes, I see, but why is Π
ok with that?
Eric Wieser (Dec 09 2021 at 17:19):
Because it's not defined like sigma?
Eric Wieser (Dec 09 2021 at 17:19):
The similarities end with the syntax being similar
Martin Dvořák (Dec 09 2021 at 17:20):
Is there a fundamental reason why Π
can be more versatile than Σ
is?
Eric Wieser (Dec 09 2021 at 17:22):
maybe this helps compare the exact differences:
universes u v
-- the most general form of pi, just so that we can #check
def Pi' {α : Sort u} (x : α → Sort v) := Π i, x i
#check @Pi'.{u v} -- Π {α : Sort u}, (α → Sort v) → Sort (imax u v)
#check @psigma.{u v} -- Π {α : Sort u}, (α → Sort v) → Sort (max 1 u v)
#check @sigma.{u v} -- Π {α : Type u}, (α → Type v) → Type (max u v)
#check @Exists.{u} -- Π {α : Sort u}, (α → Prop) → Prop
Martin Dvořák (Dec 09 2021 at 17:28):
Oh, it seems to be the magic inside imax
.
Chris B (Dec 09 2021 at 17:29):
Martin Dvořák said:
Is there a fundamental reason why
Π
can be more versatile thanΣ
is?
That's just how the type theory works. Inductive types have to abide by certain rules to keep things from being inconsistent.
Mario Carneiro (Dec 09 2021 at 17:36):
A variation on psigma
with the type Π {α : Sort u}, (α → Sort v) → Sort (imax u v)
would not be desirable, because it would not have a first projection (like exists) and would also not have proof irrelevance, so it is sort of the worst of both worlds
Mario Carneiro (Dec 09 2021 at 17:39):
(p)sigma
and exists
have fundamentally different ways of getting information out of them: sigma
has first and second projections, while Exists
uses Exists.rec
which only works for proving propositions, but on the other hand satisfies equations like \<0, trivial\> = \<1, trivial\>
(as elements of, say, \exists n : nat, true
)
Eric Wieser (Dec 09 2021 at 17:39):
(I assume you meant "like (p)sigma" and not "like exists") words are hard, "would not (have X like Y)" vs "(would not have X) like Y"
Mario Carneiro (Dec 09 2021 at 17:40):
the parenthetical refers to the previous 6 words, not just the last 2
Martin Dvořák (Dec 09 2021 at 17:47):
Can you please check for me that I extracted the main informations correctly?
image.png
Mario Carneiro (Dec 09 2021 at 17:51):
"they don't have a constructor; they live kind of beyond the system" is inaccurate. Pi
has a constructor, it is docs#expr.pi . It is a builtin term constructor, unlike all other constructors which use docs#expr.const for various choices of constant
Reid Barton (Dec 09 2021 at 17:51):
Maybe it would also help to get rid of the type theory language. Let's just define a "proposition" to be a set with at most one element. If we form the product of a bunch of propositions, the result is again a proposition. However if we form the sum of a bunch of propositions, there's no reason why the result should have at most one element. Then I can decide to either truncate it to make a proposition again, or not. That's the difference between Exists
and sigma
.
Mario Carneiro (Dec 09 2021 at 17:53):
α × β
is not shorthand syntax for Σ _ : α, β
. The former uses prod
and the latter uses sigma
. (Yes, this is not consistent with the behavior for →
/ ∀
.)
Eric Wieser (Dec 09 2021 at 17:58):
But it could have been, right? It just would have been annoying to use had it been defined that way.
Mario Carneiro (Dec 09 2021 at 17:59):
Yes, you could conceivably define it that way. You would probably want more builtin sugar for it
Mario Carneiro (Dec 09 2021 at 17:59):
I'm sure there are examples where the type inference is not as good
Chris B (Dec 09 2021 at 18:09):
Mario Carneiro said:
Pi
has a constructor, it is docs#expr.pi .
I think introducing meta inductive expr
sort of overloads the statement "Pi has a constructor" in a way that might not be helpful to someone learning the type theory.
Chris B (Dec 09 2021 at 18:15):
E.g. TPIL introduces Pi as something that's explicitly not an inductive: in Lean’s library, every concrete type other than the universes and every type constructor other than Pi is an instance of a general family of type constructions known as inductive types
.
Mario Carneiro (Dec 09 2021 at 18:15):
True. But "beyond the system" was the main thing I wanted to address. It is more primitive than usual, but still something in the system
Martin Dvořák (Dec 09 2021 at 18:18):
Mario Carneiro said:
"they don't have a constructor; they live kind of beyond the system" is inaccurate.
Pi
has a constructor, it is docs#expr.pi . It is a builtin term constructor, unlike all other constructors which use docs#expr.const for various choices of constant
What does (elaborated : bool := tt)
mean, please?
Mario Carneiro (Dec 09 2021 at 18:20):
To simplify representation, lean uses the same inductive type for both expr := expr tt
and pexpr := expr ff
, but pexpr
(pre-expression) is only used during parsing and you can ignore it for the purpose of learning the theory
Martin Dvořák (Dec 09 2021 at 18:23):
Thank you all for your replies! It will take me a longer while to understand it and summarize it. Until then, my study notes will contain those mistakes that were pointed out above.
Martin Dvořák (Dec 10 2021 at 15:16):
Chris B said:
E.g. TPIL introduces Pi as something that's explicitly not an inductive:
in Lean’s library, every concrete type other than the universes and every type constructor other than Pi is an instance of a general family of type constructions known as inductive types
.
This sentence doesn't refer to the meaning of the word instance that is connected to typeclasses, does it?
Martin Dvořák (Dec 10 2021 at 15:49):
Current version of my notes contains:
image.png
Eric Wieser (Dec 10 2021 at 15:51):
It's hard to rell from the pixels, but you seem to be using (a, b)
as notation for sigma.mk
, whereas it's actually notation for prod.mk
. Maybe those are angle brackets and the image is too small to tell though.
Martin Dvořák (Dec 10 2021 at 15:52):
Is z = (a, b)
incorrect?
Martin Dvořák (Dec 10 2021 at 15:58):
Eh. The tuple notation in parenthesis is for prod
, right? For sigma
, I should have used chevrons (langle and rangle), right?
Eric Wieser (Dec 10 2021 at 16:28):
"chevrons" work for all inductive types with one constructor, so both prod and sigma. (_, _, ...)
is only for prod
Martin Dvořák (Dec 10 2021 at 16:31):
Can I do a product of three types without nesting them? Or is it a property of the ˙( )˙ that it gets flattened?
Adam Topaz (Dec 10 2021 at 16:39):
The chevrons associate to the right, so \<_,\<_,_\>\>
is the same as \<_,_,_\>
.
Martin Dvořák (Dec 10 2021 at 16:40):
Does the same apply for parentheses?
Adam Topaz (Dec 10 2021 at 16:40):
I would imagine so...
Adam Topaz (Dec 10 2021 at 16:40):
As long as you don't define your triple product at (A \x B) \x C
, but rather use A \x B \x C
, you should be able to write (a,b,c)
(or with \<...\>
)
Martin Dvořák (Dec 10 2021 at 16:43):
Oh yes. And \times associates in the same way. For example int × Type × nat
is a short for int × (Type × nat)
.
Chris B (Dec 10 2021 at 17:11):
Martin Dvořák said:
Chris B said:
E.g. TPIL introduces Pi as something that's explicitly not an inductive:
in Lean’s library, every concrete type other than the universes and every type constructor other than Pi is an instance of a general family of type constructions known as inductive types
.This sentence doesn't refer to the meaning of the word instance that is connected to typeclasses, does it?
It does not.
Martin Dvořák (Dec 10 2021 at 17:49):
Did I get it right, please?
image.png
Horatiu Cheval (Dec 10 2021 at 18:11):
The parentheses don't stand for g.mk
, but for prod.mk
. In your notations g
is a term of a product type, the prefix is the name of the type, not the term
Martin Dvořák (Dec 10 2021 at 18:15):
Oh, thank you!
Is it all right now?
image.png
Horatiu Cheval (Dec 10 2021 at 18:19):
Well, conceptually at least yes, if you just want to use g
to simplify the notation in your notes.
Horatiu Cheval (Dec 10 2021 at 18:21):
But keep in mind that won't work as actual Lean code. If you were to define g := prod
, then g.mk
still wouldn't exist, only prod.mk
Martin Dvořák (Dec 10 2021 at 18:24):
I am not sure whether I understand you. In my snippet, I have g = τ × δ
which is g = prod τ δ
and not just g = prod
.
Martin Dvořák (Dec 10 2021 at 18:25):
Does g.mk
exists then? Or how can I write a term of the type g
without the syntactic sugar?
Eric Wieser (Dec 10 2021 at 18:26):
No, only prod.mk
exists. You'd write prod.mk bar baz
Martin Dvořák (Dec 10 2021 at 18:27):
:-o
Martin Dvořák (Dec 10 2021 at 18:27):
Does h.mk
exist?
Horatiu Cheval (Dec 10 2021 at 18:28):
Also note that there is only one prod.mk
for all \tau
and \delta
, it's not that for each two types you get some other (prod \tau \delta).mk
(that's what your notation would suggest to me)
Horatiu Cheval (Dec 10 2021 at 18:29):
No, for Sigma it's the same thing, and probably for any such type definition
Martin Dvořák (Dec 10 2021 at 18:31):
Horatiu Cheval said:
No, for Sigma it's the same thing, and probably for any such type definition
Are you replying to h.mk
here?
Horatiu Cheval (Dec 10 2021 at 18:32):
Yes
Martin Dvořák (Dec 10 2021 at 18:33):
Ah. Thanks a lot!
Martin Dvořák (Dec 10 2021 at 18:44):
When I write prod.mk
it works but when I write Σ.mk
it doesn't work. How can I invoke the constructor explicitly (without chevrons)?
Horatiu Cheval (Dec 10 2021 at 18:44):
Martin Dvořák (Dec 10 2021 at 18:58):
I wrote:
constant α : Type
constant β : α → Type
constant a : α
constant b : β a
#check sigma.mk a b
#check Σ x : α , β x
The output is:
⟨a, b⟩ : sigma β
Σ (x : α), β x : Type
By looking at it, I don't know what the relationship between them is. So I added:
def mytype := Σ x : α , β x
#check sigma.mk a b
Unfortunately, the output is again:
⟨a, b⟩ : sigma β
How can I obtain (sigma.mk a b) : mytype
please?
Horatiu Cheval (Dec 10 2021 at 19:01):
Does #check (sigma.mk a b : mytype)
work? In any case, the thing is that you have to explicitly type-annotate it
Martin Dvořák (Dec 10 2021 at 19:02):
By #check (sigma.mk a b : mytype)
I obtain ⟨a, b⟩ : Σ (x : α), β x
which makes me more happy than the previous thing.
Martin Dvořák (Dec 10 2021 at 19:09):
What would happen if, for concrete types, I would end up with β a
being int
for example? Would it still know that a term constructed by sigma.mk a 5
is of the type mytype
?
Horatiu Cheval (Dec 10 2021 at 19:12):
The way it's written here no, I don't think you will be able to do def x : mtytype := sigma.mk a 5
, because mytype
is just Type
, it's not parametrized. In your definition \alpha
and \beta
are fixed constants, so they argument for the type mytype
Horatiu Cheval (Dec 10 2021 at 19:12):
You would be able to do that if used variable
instead of constant
for example
Martin Dvořák (Dec 10 2021 at 19:17):
Is it now correct?
image.png
Martin Dvořák (Dec 10 2021 at 19:21):
I originally (wrongly) assumed that I could use mytype.mk
and I would get (when provided correct arguments) a term of the type mytype
. Now I can see that I cannot do it.
As a result, it makes me uncomfortable that I must write e.g. sigma.mk 5 9
but there are many possible sigma types which my term could be an instance of.
Horatiu Cheval (Dec 10 2021 at 19:23):
It seems correct
Horatiu Cheval (Dec 10 2021 at 19:23):
But I don't really understand your last statement
Martin Dvořák (Dec 10 2021 at 19:24):
The reason is that there are many possibly functions that send 5
to nat
Martin Dvořák (Dec 10 2021 at 19:26):
Let's say I have f : int -> Type
and g : int -> Type
. Let's say they agree on the value of f 5 = nat = g 5
. Now I call sigma.mk 5 9
. Do I have an instance of sigma f
or of signa g
?
Horatiu Cheval (Dec 10 2021 at 19:26):
Does that even typecheck? It shouldn't
Horatiu Cheval (Dec 10 2021 at 19:26):
I'm talking about sigma.mk 5 9
Horatiu Cheval (Dec 10 2021 at 19:26):
Because 9
is not a function
Martin Dvořák (Dec 10 2021 at 19:27):
Why should I put function on the position of 9
in my expression? I have f 5 = nat
and not something like f 5 = (nat -> nat)
.
Adam Topaz (Dec 10 2021 at 19:28):
In general you need to use type annotations to tell lean what the type family is when defining a term of a sigma type.
Martin Dvořák (Dec 10 2021 at 19:29):
Should I write something like let myvalue := (sigma.mk 5 9 : mytype)
?
Horatiu Cheval (Dec 10 2021 at 19:29):
Oh right, sorry. I thought you meant sigma 5 9
Adam Topaz (Dec 10 2021 at 19:29):
What's mytype
?
Martin Dvořák (Dec 10 2021 at 19:31):
Adam Topaz said:
What's
mytype
?
Say Σ x : int, f x
.
Adam Topaz (Dec 10 2021 at 19:31):
def foo : Σ (n : ℕ), ℕ := ⟨2,3⟩
def bar : Σ (n : ℕ), ℤ := ⟨2,3⟩
lemma does_not_typecheck : foo = bar := sorry
Adam Topaz (Dec 10 2021 at 19:32):
I would write let myvalue : mytype := ...
Adam Topaz (Dec 10 2021 at 19:32):
If you want to define something inline, then you can do (... : mytype)
Adam Topaz (Dec 10 2021 at 19:36):
Maybe a better example:
def f : ℕ → Type
| 0 := ℕ
| 1 := ℤ
| _ := ℕ
def g : ℕ → Type
| _ := ℤ
def foo : sigma f := ⟨1, (2 : ℤ)⟩
def bar : sigma g := ⟨1, (2 : ℤ)⟩
lemma also_does_not_typecheck : foo = bar := sorry
Martin Dvořák (Dec 10 2021 at 19:37):
Thank you! Your last example explains a lot!
Martin Dvořák (Dec 10 2021 at 19:51):
I still wasn't technically correct, was I?
image.png
Here (prod.mk bar baz)
automatically becomes a term of the type τ × δ
hence it can be used as an argument of the type g
. This isn't true for (sigma.mk bar baz)
because I would have to explicitly say that I want a term of the type h
(or something definitionally equal to h
).
Adam Topaz (Dec 10 2021 at 19:52):
The type will generally not be inferred from context if you only write sigma.mk a b
or \<a,b\>
.
Martin Dvořák (Dec 10 2021 at 19:52):
But it will be inferred for (a,b)
, right?
Adam Topaz (Dec 10 2021 at 19:52):
Even if you write sigma.mk a b
, there will be a metavariable because lean wouldn't know what the type family is without further hints
Adam Topaz (Dec 10 2021 at 19:53):
For (a,b)
you will get a term of the product, and since lean knows the type of a
and b
, the type of (a,b)
is inferred correctly.
Martin Dvořák (Dec 10 2021 at 19:53):
For prod.mk a b
I will automatically get inferred the right type.
Adam Topaz (Dec 10 2021 at 19:57):
Try this out in a vscode and see what happens:
def foo := sigma.mk (1 : ℕ) (2 : (λ t, ℕ) 1)
def bar := sigma.mk (1 : ℕ) (2 : ℕ)
Martin Dvořák (Dec 10 2021 at 19:59):
Only the first one passes the typecheck!
Martin Dvořák (Dec 10 2021 at 20:04):
Mario Carneiro said:
I'm sure there are examples where the type inference is not as good
Is [the thing we discussed today (above)] an example of what you were talking about?
Martin Dvořák (Dec 10 2021 at 20:06):
Adam Topaz said:
The type will generally not be inferred from context if you only write
sigma.mk a b
or\<a,b\>
.
highlight 1
Martin Dvořák (Dec 10 2021 at 20:06):
(deleted)
Martin Dvořák (Dec 10 2021 at 20:07):
Adam Topaz said:
For
(a,b)
you will get a term of the product, and since lean knows the type ofa
andb
, the type of(a,b)
is inferred correctly.
highlight 2
Martin Dvořák (Dec 10 2021 at 20:09):
@Mario Carneiro To save you some scrolling and reading, just have a look at the two comments (highlight 1 & 2) above. Is it the motivation you were talking about — sigma could be used for prod but the type inference would be worse.
Wojciech Nawrocki (Dec 11 2021 at 00:45):
Apologies to derail slightly with a tangential question -- @Martin Dvořák are you using some mind/concept mapping software in the screenshots? If so, which?
Mario Carneiro (Dec 11 2021 at 04:10):
@Martin Dvořák Sure, yes that's an example. I haven't seen the trick with using a beta redex for the second pair element before, but it makes sense that it would work
Martin Dvořák (Dec 13 2021 at 10:52):
Wojciech Nawrocki said:
Apologies to derail slightly with a tangential question -- Martin Dvořák are you using some mind/concept mapping software in the screenshots? If so, which?
Yes, it is OrgPad.
https://orgpad.com/
I will be glad if you give me any comments on my (current version of) study notes about Lean.
https://orgpad.com/s/ZBGjrzoGIBb
Last updated: Dec 20 2023 at 11:08 UTC