# Zulip Chat Archive

## Stream: new members

### Topic: Invoking instances explicitly

#### Jakob Scholbach (Mar 03 2021 at 22:26):

For some integral domain F, I have a hypothesis `char_zero F`

. I would like to infer `char_p F 0`

using

```
instance char_p.of_char_zero (α : Type u) [semiring α] [char_zero α] : char_p α 0 :
```

If I write `apply char_p.of_char_zero `

etc., it does not work. I guess this is because that fact is declared as an `instance`

, not a `lemma`

. How do I invoke this instance explicitly in order to gain a new hypothesis `char_p F 0`

in this case?

#### Eric Wieser (Mar 03 2021 at 22:28):

Can you give a #mwe?

#### Yakov Pechersky (Mar 03 2021 at 22:30):

Have you done

```
haveI : char_p F 0 := of_char_zero your_hypothesis,
```

#### Adam Topaz (Mar 03 2021 at 22:30):

```
import algebra.char_p.basic
example (α : Type*) [semiring α] [char_zero α] : char_p α 0 := by apply_instance
```

#### Adam Topaz (Mar 03 2021 at 22:31):

So the typeclass system will find the instance automatically.

#### Adam Topaz (Mar 03 2021 at 22:34):

Here's a little game you can play to see that this actually works inside a proof:

```
import algebra.char_p.basic
example (α : Type*) [semiring α] [char_zero α] : char_p α 0 := by apply_instance
def foo {α : Type*} [semiring α] [char_p α 0] : α := 0
lemma this_is_a_thing (α : Type*) [semiring α] [char_zero α] : true :=
begin
have := (foo : α),
sorry
end
```

#### Kevin Buzzard (Mar 03 2021 at 22:35):

The idea is that "the system" (the type class inference system) is supposed to deal with all the terms of type `X`

if `X`

is a so-called "class". It is doing this all the time -- if you write `[ring R]`

and then want to use `add_zero`

to prove `r + 0 = r`

, for some `r : R`

, Lean has a problem, because `#check @add_zero`

shows this:

```
add_zero : ∀ {M : Type u_1} [_inst_1 : add_monoid M] (a : M), a + 0 = a
```

In other words, `add_zero`

is a theorem which applies to all `add_monoid`

s. But `R`

is a ring, which to Lean means that there is a term `_inst_1 : ring R`

which is known to the type class system. However the type class system also knows that every `ring`

is an `add_monoid`

, as can be checked like this:

```
example (R : Type) [ring R] : add_monoid R := by apply_instance
```

so the lemma applies automatically, because the type class system does the job of finding the correct term of type `add_monoid R`

which `add_zero`

needs as an input.

```
example (R : Type) [ring R] (r : R) : r + 0 = r := add_zero r -- works!
```

#### Jakob Scholbach (Mar 03 2021 at 22:37):

@Eric Wieser :

```
import algebra.char_p.basic
import algebra.char_zero
lemma aux (F: Type) [integral_domain F] (hq : true ∧ char_zero F) : char_p F 0 :=
begin
have hyp : char_zero F := hq.2,
-- here I want to apply char_p.of_char_zero to hyp,
sorry
end
```

(I know the assumption hq with the `true \and `

is a bit stupid. If I remove the `true \and `

bit, then `apply char_p.of_char_zero,`

precisely works, but if I generate the hypothesis `hyp`

in the middle of the proof it won't work.

#### Adam Topaz (Mar 03 2021 at 22:40):

```
import algebra.char_p.basic
import algebra.char_zero
lemma aux (F: Type) [integral_domain F] (hq : true ∧ char_zero F) : char_p F 0 :=
begin
haveI := hq.2,
apply_instance
end
```

#### Adam Topaz (Mar 03 2021 at 22:40):

The `fooI`

instances let you introduce instances to the typeclass system inside a tactic block.

#### Kevin Buzzard (Mar 03 2021 at 22:42):

`char_zero`

is a class, but you didn't put it in square brackets before the colon, so the type class inference system ignored it. The usual way to get something into the system is square brackets before the colon, and `haveI`

is a way to add things in the middle of a proof. Another useful one is `resetI`

which adds all the instances of the classes which are hypotheses.

#### Kevin Buzzard (Mar 03 2021 at 22:43):

```
import algebra.char_p.basic
import algebra.char_zero
lemma aux (F: Type) [integral_domain F] (hq : true ∧ char_zero F) : char_p F 0 :=
begin
cases hq with h1 h2, -- now `h2 : char_zero F` is an assumption
resetI, -- now it's in the type class system
apply_instance -- works
end
```

#### Jakob Scholbach (Mar 03 2021 at 22:43):

OK, learned another thing -- thank you all!

#### Adam Topaz (Mar 03 2021 at 22:44):

The issue you originally faced was that `[char_zero F]`

was a required instance in `char_p.of_char_zero`

, and you didn't have that in context. If you want to do things fully explicitly, you can do something like this:

```
import algebra.char_p.basic
import algebra.char_zero
lemma aux (F: Type) [integral_domain F] (hq : true ∧ char_zero F) : char_p F 0 :=
begin
have claim := hq.2,
exact @char_p.of_char_zero F _ hq.2
end
```

#### Kevin Buzzard (Mar 03 2021 at 22:46):

Type class inference took me a long time to master. A lot of the examples in the docs are pretty non-mathematical. This is the reason I mentioned the `ring`

example. Another example is notation: `instance has_add X := ⟨foo⟩`

makes `x + y`

mean `foo x y`

, because `+`

is notation for `has_add.add`

, and if you `#check @has_add.add`

you'll see that it asks the type class inference system for a term of type `has_add X`

, which the `instance`

has put there.

#### Jakob Scholbach (Mar 03 2021 at 22:50):

@Kevin Buzzard : yes, if you are going to expand the Mathematics in Lean documentary, please do include such explanations.

#### Jakob Scholbach (Mar 03 2021 at 22:52):

I didn't know the `haveI`

(nor `resetI`

), and it also doesn't seem to be discussed in the Theorem Proving in Lean doc.

#### Kevin Buzzard (Mar 03 2021 at 22:53):

No, these things are well-kept secrets ;-) They are part of mathlib and were introduced after TPIL was written.

#### Adam Topaz (Mar 03 2021 at 22:53):

@Jakob Scholbach do you know about the tactic documentation here? https://leanprover-community.github.io/mathlib_docs/tactics.html

#### Kevin Buzzard (Mar 03 2021 at 22:54):

Just keep asking here if you are not sure about anything -- you see that four people had responded to your question within ten minutes of you asking.

#### Jakob Scholbach (Mar 03 2021 at 22:56):

Yes, I am grateful for all your immediate help -- absolutely stellar! Do you guys never sleep? :)

@Adam Topaz , I stumbled over it once, but didn't realize its importance yet. I will try to digest it then; thanks again.

#### Adam Topaz (Mar 03 2021 at 22:57):

Some of us are in the western hemisphere :) I don't know why all these people in Europe are still awake! :rofl:

#### Kevin Buzzard (Mar 03 2021 at 22:58):

I'm preparing my lecture on quotients in Lean for tomorrow!

#### Johan Commelin (Mar 04 2021 at 05:29):

I see that the problem is already solved, but @Jakob Scholbach how did you end up with `hq : true ∧ char_zero F`

? Because that's not supposed to happen :wink: :smiley:

#### Patrick Massot (Mar 04 2021 at 07:49):

Kevin Buzzard said:

`char_zero`

is a class, but you didn't put it in square brackets before the colon, so the type class inference system ignored it.

Technically this explanation is wrong. The kind of brackets you use in a `def`

or statement matters only when *using* it.

```
import algebra.char_p.basic
import algebra.char_zero
lemma aux (F: Type) (hi : integral_domain F) (hq : char_zero F) : char_p F 0 :=
begin
apply_instance, -- works
end
```

The way Lean picks up instance assumptions when elaborating the part right of the colon (and what is in the system at the beginning of the proof) seems to be simply looping through the context and looking for type classes, but not looking inside inductive constructors like Jakob's and.

#### Kevin Buzzard (Mar 04 2021 at 08:04):

Aah yes, I've been confused by this before. Thanks!

#### Jakob Scholbach (Mar 04 2021 at 10:14):

@Johan Commelin : Yes, sure, this was a bit silly; this was just in order to have a minimal example. In the real situation I had a conjunction like `p = 1 \and char_zero F`

, in the process of writing down some basic lemmas about the exponential characteristic.

#### Johan Commelin (Mar 04 2021 at 10:17):

Ok, understood. But whenever possible you should try to split such conjunctions into two separate hypotheses. Then you can feed `[char_zero F]`

to TC.

Last updated: Dec 20 2023 at 11:08 UTC