Zulip Chat Archive

Stream: lean4

Topic: constructor is the new split


Kevin Buzzard (Apr 03 2023 at 17:56):

Am I really supposed to be telling the undergraduates that when faced with ⊢ P ∧ Q they now have to type constructor (because split now means something else)? Is there something less verbose which turns this into two goals P and Q?

Kevin Buzzard (Apr 03 2023 at 17:57):

I guess I could introduce pointy brackets and do refine \<_, _\>...

Matthew Ballard (Apr 03 2023 at 17:58):

Can you write a small macro or is split reserved?

Eric Wieser (Apr 03 2023 at 18:09):

Or apply and.intro which is more verbose, but at least the first 5 characters are something they already know

Kevin Buzzard (Apr 03 2023 at 18:13):

I can't write a small macro whether or not split is reserved. Is there some basic "writing small macros in lean 4 for dummies" md file somewhere?

When I was slowly but surely learning Lean 3, when random stuff like this came up (looks like a useful skill or thing to know, no obviously nice reference for dummies) I would badger people until I understood enough myself and then I'd write a small md file and dump it in the Xena Project chaos. I'm talking 2018 here. Then I'd start linking to it in various places, and pointing people to it on the chat. Then the lean prover community decided that some of the stuff I was generating was useful for the community, and moved it to the community website. This is the origin of files such as this. Eventually someone would come along and just be annoyed by my amateurish attempts to explain stuff and just rewrite them completely, and then they became even more useful.

I wonder if there's room for this kind of document on the community website for lean 4 "tips and tricks"? Or another place to put stuff like this?

Kevin Buzzard (Apr 03 2023 at 18:15):

The calc mode file was also mine, Patrick wrote the conv mode file, and Chris Hughes wrote the well-founded recursion file because I nagged him to write it because I found it completely impossible to work out with no reference. At the time the only reference we had was #tpil . In the early days of the community when only a few people knew the contents of those files, this stuff was super-useful.

Matthew Ballard (Apr 03 2023 at 18:23):

macro_rules | `(tactic| split) => `(tactic| constructor)

seems to work

Newell Jensen (Apr 03 2023 at 18:23):

You can also use angle brackets, fwiw

example : s  q  r  p  r  q  p := by
  intro _, hq, _⟩⟩ hp, _
  exact hq, hp

Patrick Massot (Apr 03 2023 at 18:33):

Kevin, if you write useful doc then we'll find or create a place for it.

Kevin Buzzard (Apr 03 2023 at 18:45):

OK! How do I make my_induction n with d hd do induction' a using MyNat.induction with d hd?

Kevin Buzzard (Apr 03 2023 at 18:46):

Here myNat.induction is a custom induction principle which uses the numeral 0 rather than MyNat.zero.

Kevin Buzzard (Apr 03 2023 at 18:49):

:cry:

case a
 0 + 0 = 0
case a
d: MyNat
hd: 0 + d = d
 0 + succ d = succ d

Even better, how do I make the cases be zero and succ?
mwe:

import Mathlib.Algebra.Group.Defs -- `import tactic` in mathlib4

whatsnew in
inductive MyNat : Type
| zero : MyNat
| succ : MyNat  MyNat

namespace MyNat

-- notational typeclass for 0
instance : Zero MyNat where
  zero := MyNat.zero

#check (0 : MyNat)

theorem induction : {P : MyNat  Prop} 
  (t : MyNat)  P (0 : MyNat)  ((a : MyNat)  P a  P (a.succ))  P t :=
fun {_} t zero succ => MyNat.rec zero succ t

def add (a : MyNat) : MyNat  MyNat
| zero => a
| (succ b) => succ (add a b)

instance : Add MyNat where
  add := add

theorem zero_add (a : MyNat) : 0 + a = a := by
  induction' a using MyNat.induction with d hd
/-
unsolved goals
case a
⊢ 0 + 0 = 0

case a
d : MyNat
hd : 0 + d = d
⊢ 0 + succ d = succ d
-/

Kyle Miller (Apr 03 2023 at 18:57):

Naming the arguments should be sufficient:

theorem induction : {P : MyNat  Prop} 
  (t : MyNat)  (zero : P (0 : MyNat))  (succ : (a : MyNat)  P a  P (a.succ))  P t :=
fun {_} t zero succ => MyNat.rec zero succ t

Heather Macbeth (Apr 03 2023 at 18:59):

Kevin Buzzard said:

OK! How do I make my_induction n with d hd do induction' a using MyNat.induction with d hd?

@Kevin Buzzard
https://github.com/hrmacbeth/math2001/blob/7b7e5f59ec0fc832cf4f80fd23a4495e6108b2b3/Math2001/Tactic/Induction.lean#L46
(courtesy @Rob Lewis)

Kevin Buzzard (Apr 03 2023 at 19:01):

Heh, it was Rob who told me all the tactic hacks to make this work in lean 3 :-) Hi Rob!

Kyle Miller (Apr 03 2023 at 19:16):

@Kevin Buzzard It looks like you don't need a custom induction tactic. The @[eliminator] attribute can be used to override which eliminator to use.

import Mathlib.Algebra.Group.Defs

inductive MyNat : Type
| zero : MyNat
| succ : MyNat  MyNat

namespace MyNat

instance : Zero MyNat where
  zero := MyNat.zero

@[eliminator]
theorem induction : {P : MyNat  Prop} 
  (t : MyNat)  (zero : P (0 : MyNat))  (succ : (a : MyNat)  P a  P (a.succ))  P t :=
fun {_} t zero succ => MyNat.rec zero succ t

def add (a : MyNat) : MyNat  MyNat
| zero => a
| (succ b) => succ (add a b)

instance : Add MyNat where
  add := add

theorem zero_add (a : MyNat) : 0 + a = a := by
  induction' a with d hd
  /-
  case zero
  ⊢ 0 + 0 = 0

  case succ
  d: MyNat
  hd: 0 + d = d
  ⊢ 0 + succ d = succ d
  -/

end MyNat

Moritz Doll (Apr 03 2023 at 23:28):

Kevin Buzzard said:

I can't write a small macro whether or not split is reserved. Is there some basic "writing small macros in lean 4 for dummies" md file somewhere?

Actually, I thought about writing a small 'tactic writing for dummies' file (mainly to not forget what I have learned). If there is real interest in that, I can put it higher on my todo list.

James Gallicchio (Apr 03 2023 at 23:39):

I know it's long/has way more information than you might want, but the examples in the metaprogramming book are a pretty good cheat sheet. E.g. here for macros


Last updated: Dec 20 2023 at 11:08 UTC