## Stream: new members

### Topic: from inclusion to belonging

#### Arthur Paulino (Oct 27 2021 at 15:49):

If I have e: ↥(G.incidence_set ↑v) and h': ∀ (v : V), G.incidence_set v ⊆ G.edge_set, how do I use h' to prove that e belongs to G.edge_set?

#### Johan Commelin (Oct 27 2021 at 15:54):

Just apply it (-;

#### Johan Commelin (Oct 27 2021 at 15:54):

h _ e

#### Kevin Buzzard (Oct 27 2021 at 15:55):

The definition of A ⊆ B is ∀ x, x ∈ A → x ∈ B, so tactics like apply (which work up to definitional equality) will work.

#### Kevin Buzzard (Oct 27 2021 at 15:56):

h' _ e or similar

#### Arthur Paulino (Oct 27 2021 at 16:03):

type mismatch at application
h' ?m_1 e
term
e
has type
↥(G.incidence_set ↑v) : Type u
but is expected to have type
?m_1 ∈ G.incidence_set ?m_2 : Prop


Something I've been intending to ask for a while: what are those arrows pointing up (↥ and ↑)?

#### Bryan Gin-ge Chen (Oct 27 2021 at 16:05):

These are coercion arrows. They are also covered in chapter 10 of TPiL: https://leanprover.github.io/theorem_proving_in_lean/type_classes.html#coercions-using-type-classes

#### Kevin Buzzard (Oct 27 2021 at 16:07):

Perhaps now is the time to explain this, because that error is a bit more complicated to debug.

#### Kevin Buzzard (Oct 27 2021 at 16:09):

It seems to me that  G.incidence_set v and G.edge_set are probably sets, because of (a) their name and (b) the fact that G.incidence_set v ⊆ G.edge_set typechecks. But Lean uses type theory, not set theory. Everything in Lean is either a universe, a type, or a term -- it exists at one of those three levels. Sets exist at the term level -- they are not types. But you have e: ↥(G.incidence_set ↑v), so e is a term and its type is ↥(G.incidence_set ↑v), which is the type corresponding to the set G.incidence_set ↑v.

#### Kevin Buzzard (Oct 27 2021 at 16:11):

So strictly speaking your original question does not even make sense: e is a term of the type ↥(G.incidence_set ↑v), and in particular it is not a term of type sym2 V (the set of unordered pairs of elements of V), so e cannot belong to G.edge_set.

#### Kevin Buzzard (Oct 27 2021 at 16:12):

What is going on is that if X is a type (e.g. sym2 V) and if S : set X is a subset of X then there is an associated type ↥S, and a term of this type is a pair consisting of x : X and a proof hx : x ∈ S.

#### Kevin Buzzard (Oct 27 2021 at 16:13):

So e in your code is this pair; the element itself is called e.1 and the proof that it's in the set is called e.2. The error indicates that where you put e Lean was expecting a proof, so I would replace e with e.2.

#### Arthur Paulino (Oct 27 2021 at 16:17):

So that's why I can use e.val and e.property? .val being the same as .1 and .property the same as .2?

#### Kevin Buzzard (Oct 27 2021 at 16:17):

yeah, those are the same thing

#### Kevin Buzzard (Oct 27 2021 at 16:18):

e.val is the value (the term of type sym2 V) and e.property is the proof that it's in the set which you're coercing to a type

#### Kevin Buzzard (Oct 27 2021 at 16:20):

The various flavours of arrows indicate when you want to conflate things which Lean thinks are different and which you might want to treat as the same; for example

example (a : ℤ) (b : ℕ) : a = b :=
begin
-- ⊢ a = ↑b
sorry
end


the arrow means "yeah b is a natural, but we want it to be an integer, so we apply the obvious function from naturals to integers"

#### Kevin Buzzard (Oct 27 2021 at 16:22):

That simple up-arrow is the most common, where terms get moved to terms. The one with the bottom edge is a more drastic one, where terms get moved to types. We see this in your setting because sets are terms because this is type theory not set theory. set X is the type of subsets of X, and S : set X is a term of that type, i.e. a subset of X, but it's not a type itself.

#### Arthur Paulino (Oct 27 2021 at 16:25):

And now, after apply h' _ e.property, it says:

invalid apply tactic, failed to unify
↥(G.edge_set)
with
e.val ∈ G.edge_set


#### Kevin Buzzard (Oct 27 2021 at 16:25):

yup, I can't unify those either. Are you up to posting some Lean code which I can run at my end yet?

#### Mario Carneiro (Oct 27 2021 at 16:26):

Showing the types of things will also help

#### Arthur Paulino (Oct 27 2021 at 16:27):

This is the complete state description:

V: Type u
G: simple_graph V
_inst_1: decidable_eq V
_inst_2: fintype ↥(G.edge_set)
_inst_3: fintype V
_inst_4: nonempty V
h: G.is_tree
root: V
v: ↥{v : V | v ≠ root}
e: ↥(G.incidence_set ↑v) := next_edge ↑v root _ ↑(G.tree_path h ↑v root)
h': ∀ (v : V), G.incidence_set v ⊆ G.edge_set := G.incidence_set_subset
⊢ ↥(G.edge_set)


#### Kevin Buzzard (Oct 27 2021 at 16:30):

So something odd is happening. You can specialize h' v probably, and then specialize h' e.2 after that

#### Kevin Buzzard (Oct 27 2021 at 16:30):

but it's much harder to help without having working code running in my own VS Code

#### Mario Carneiro (Oct 27 2021 at 16:30):

exact \<_, h' _ e.2\> should work

#### Mario Carneiro (Oct 27 2021 at 16:31):

assuming that you want to prove that e.1 is the element in the set

#### Arthur Paulino (Oct 27 2021 at 16:32):

The code is from that branch I pointed earlier: more_on_trees. I still find it hard to cut the exact pieces of the code and paste only essential things here

#### Kevin Buzzard (Oct 27 2021 at 16:32):

but even when I tried to use that branch I couldn't get it working -- there were errors on a file you were importing

#### Kevin Buzzard (Oct 27 2021 at 16:33):

if you can just push to the branch then I can pull and compile but the last time I tried that the first error was way before the part you were talking about, and I am reluctant to look at code beyond the first error in a file.

#### Kevin Buzzard (Oct 27 2021 at 16:34):

errors in files have weird and unintended consequences

#### Arthur Paulino (Oct 27 2021 at 16:37):

branch updated. Kyle did what Mario proposed: exact ⟨_, e.property.1⟩
but I was trying to do it differently

#### Arthur Paulino (Oct 27 2021 at 16:44):

This was my line of thought... please notice that I'm still figuring things out:
When Lean reads let f : {v | v ≠ root} → G.edge_set, it requests that I express how to take an element of {v | v ≠ root} to an element of G.edge_set. And the goal ↥(G.edge_set) is how Lean demands it.
Is it what's happening?

#### Kevin Buzzard (Oct 27 2021 at 17:13):

Yes -- if you want to define a function in the middle of a tactic proof it's probably best to do it directly with λ etc: let f : {v | v ≠ root} → G.edge_set := λ w, ...

Last updated: Dec 20 2023 at 11:08 UTC