Zulip Chat Archive

Stream: new members

Topic: induction tactic failed


Alex Zhang (Jul 24 2021 at 14:21):

This is an #mwe I extracted, how can I get across this problem?

import tactic
import field_theory.finite.basic
import number_theory.quadratic_reciprocity

variables {F : Type*} [field F] [fintype F] [decidable_eq F]
example : field F :=
begin
  have exist_p := char_p.exists F,
  cases exist_p,
end

Alex Zhang (Jul 24 2021 at 14:21):

the error message is induction tactic failed, recursor 'Exists.dcases_on' can only eliminate into Prop

Reid Barton (Jul 24 2021 at 14:36):

This example is too minimal

Reid Barton (Jul 24 2021 at 14:37):

obviously, you should just use the [field F] hypothesis here

Reid Barton (Jul 24 2021 at 14:37):

The error message means: you can't do cases on an existential when you're trying to define data (like a field instance)

Reid Barton (Jul 24 2021 at 14:39):

In this case though, a field has exactly one characteristic. So there must be something other than char_p.exists you can use to get it.

Alex Zhang (Jul 24 2021 at 14:44):

The key problem is how I can extract a char for F in a definition constructing something.
The thing can even be a graph

import tactic
import field_theory.finite.basic
import combinatorics.simple_graph.basic

variables {F V : Type*} [field F] [fintype F] [decidable_eq F]

include F
example : simple_graph V :=
begin
  have exist_p := char_p.exists F,
    cases exist_p,
end

Alex Zhang (Jul 24 2021 at 14:46):

cases or rcases or obtain will report errors

Reid Barton (Jul 24 2021 at 14:47):

char_p.exists is the wrong thing to use here.

Reid Barton (Jul 24 2021 at 14:47):

What you want is the characteristic of the field, not just knowing that it has some characteristic.

Alex Zhang (Jul 24 2021 at 14:52):

What should be the right lemma to use then? :thinking:

Reid Barton (Jul 24 2021 at 14:53):

You don't want a lemma, you want a definition.

Reid Barton (Jul 24 2021 at 14:53):

I would just read random files about fields until I found out what it is.

Alex Zhang (Jul 24 2021 at 14:55):

Yeah, I want a def based on the char of F.

Reid Barton (Jul 24 2021 at 15:04):

Also, it's usually not a good idea to make a definition using tactics unless you're careful about which tactics you use where.

Reid Barton (Jul 24 2021 at 15:08):

Because later you're presumably going to want to prove something about what you defined, and for that you will need to know what term was produced (and you probably don't want that term to start with something like have exist_p := char_p.exists F, exist_p.rec (\lam p, ...))

Adam Topaz (Jul 24 2021 at 15:15):

You can use docs#ring_char to get the characteristic of a field (or even a possibly non associative semiring) as a natural number. I would also take a look at how it's implemented which should help with some of the questions you have above.

Adam Topaz (Jul 24 2021 at 15:16):

The associated API should all have the form ring_char.foo

Eric Rodriguez (Jul 24 2021 at 15:30):

in general, though, if you have a goal with typing judgement in Type* and you want to get the data out of an Exists, then you have to use classical.some and classical.some_spec; I've suggested a obtain! that lets you get round this error, but I haven't gotten round to coding it. The reason that you can even obtain on when you're making a Prop is because of proof irrelevance

Kevin Buzzard (Jul 24 2021 at 15:33):

It's also worth remarking that if you have a tactic mode goal whose type is Type* then you're probably doing something wrong anyway: goals should have type Prop in tactic mode.

Alex Zhang (Jul 24 2021 at 15:36):

If it is to construct an instance of some class containing only several propositions, I don't see a problem with using tactics.

Kevin Buzzard (Jul 24 2021 at 15:46):

simple_graph contains adj, which is data.

Kevin Buzzard (Jul 24 2021 at 15:46):

If a class just contains propositions, then it will be a proposition itself.

Kevin Buzzard (Jul 24 2021 at 15:48):

To make an instance of any structure (e.g. a class) I guess the standard way to do it is to use the usual constructor, e.g.

example : simple_graph V :=
{ adj := _,
  sym := _,
  loopless := _ }

rather than launching into tactic mode with begin.

Alex Zhang (Jul 24 2021 at 15:48):

Yeah, simple_graph is not an example for a class of props.

Alex Zhang (Jul 24 2021 at 15:50):

nontrivial is an example

Kevin Buzzard (Jul 24 2021 at 15:52):

right, and it's a Prop, so you can use begin/end for that, but it would probably be wiser to use some structure constructor instead for example ⟨begin ... end⟩

Reid Barton (Jul 24 2021 at 15:52):

Alex Zhang said:

nontrivial is an example

Right but you wouldn't have gotten the original error about Exists.dcases_on if your goal was really a Prop. That's why I suggested the example was too minimized.

Alex Zhang (Jul 24 2021 at 15:58):

Ah, I see, if the type of the structure is :Prop , the problem will not occur.

Kevin Buzzard (Jul 24 2021 at 16:00):

Exactly. cases and other related commands call the recursor for the structure in question, and if the structure only eliminates into Prop then you won't be able to use it in tactic mode if the goal isn't a Prop.

Alex Zhang (Jul 24 2021 at 16:01):

I encountered this issue as I did not write : Prop is the structure declaration like the following:

import tactic
import field_theory.finite.basic
import number_theory.quadratic_reciprocity

variables {F : Type*} [field F] [fintype F] [decidable_eq F]

class struct1 :=
(prop1 : true)
(prop2 : true)

include F
example : struct1 :=
begin
  have exist_p := char_p.exists F,
  cases exist_p,
end

Kevin Buzzard (Jul 24 2021 at 16:01):

For example or.rec is

or.rec :  {a b C : Prop}, (a  C)  (b  C)  a  b  C

and because C : Prop you won't be able to do cases on h : a ∨ b if your goal is not a Prop.

Reid Barton (Jul 24 2021 at 16:02):

Yes, this structure/class defaulting to Type mistake is really easy to make.

Kevin Buzzard (Jul 24 2021 at 16:03):

One could argue that this is a bug in Lean. This sort of thing even makes its way into mathlib occasionally.

Eric Rodriguez (Jul 24 2021 at 16:04):

technical sidenote but shouldn't singleton elimination kick in for struct1? or do I understand singleton elimination wrong

Kevin Buzzard (Jul 24 2021 at 16:05):

exists eliminates into Prop and this has nothing to do with subsingleton elimination. Lean cannot solve for C and that's the end of it, so the cases tactic doesn't work.

Kevin Buzzard (Jul 24 2021 at 16:06):

As has already been observed, there are other ways around this, but they use other tactics.

Alex Zhang (Jul 24 2021 at 16:08):

@Eric Rodriguez Could you show how to use classical.some or classical.some_spec in the very first example?

Eric Rodriguez (Jul 24 2021 at 16:10):

import tactic
import field_theory.finite.basic
import number_theory.quadratic_reciprocity

variables {F : Type*} [field F] [fintype F] [decidable_eq F]
example : field F :=
begin
  have exist_p := char_p.exists F,
  have hp := classical.some_spec exist_p,
  -- hp: char_p F (classical.some exist_p)
end

Last updated: Dec 20 2023 at 11:08 UTC