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):

docs#sigma.mk

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 of a and b, 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