Zulip Chat Archive
Stream: Is there code for X?
Topic: using `cons` as match_pattern
Asei Inoue (Jun 07 2024 at 15:32):
inductive Many (α : Type) where
| none : Many α
| more : α → (Unit → Many α) → Many α
@[match_pattern]
def cons (x : α) (xs : Many α) : Many α :=
.more x (fun () => xs)
def Many.union : Many α → Many α → Many α
| Many.none, ys => ys
| Many.more x xs, ys => Many.more x (fun () => union (xs ()) ys)
instance : Append (Many α) where
append := Many.union
/- error: invalid alternative name 'cons' -/
theorem union_none (x : α) (xs : Many α) : xs ++ .none = xs := by
induction xs with
| none => rfl
| cons x xs ih => sorry
Asei Inoue (Jun 07 2024 at 15:32):
I want to use this cons
function for induction
...
Shreyas Srinivas (Jun 07 2024 at 15:36):
Is this a lazy list?
Shreyas Srinivas (Jun 07 2024 at 15:36):
@loogle LazyList
loogle (Jun 07 2024 at 15:36):
:search: LazyList, LazyList.iota, and 66 more
Asei Inoue (Jun 07 2024 at 15:36):
see https://lean-lang.org/functional_programming_in_lean/monads/arithmetic.html#nondeterministic-search
Kyle Miller (Jun 07 2024 at 16:19):
The induction
tactic doesn't use match
infrastructure. The @[match_pattern]
attribute doesn't apply here at all.
You could write an @[induction_eliminator]
to save you from writing using myEliminatorTheorem
in induction xs using myEliminatorTheorem with ...
. You'll have to write myEliminatorTheorem
(it should copy how Many.recOn
looks, but you can adjust the statement to have a cons
minor hypothesis).
Asei Inoue (Jun 08 2024 at 03:06):
@Kyle Miller Thank you. How can I enable cons to be used in pattern matching by match? I have created a cons version of Many.casesOn, but it does not work.
Asei Inoue (Jun 08 2024 at 03:07):
inductive Many (α : Type) where
| none : Many α
| more : α → (Unit → Many α) → Many α
@[match_pattern]
def Many.cons (x : α) (xs : Many α) : Many α :=
.more x (fun () => xs)
@[match_pattern]
protected def Many.cons_casesOn.{u} {α : Type} {motive : Many α → Sort u} (t : Many α) (none : motive Many.none)
(cons : (a : α) → (b : Many α) → motive (Many.cons a b)) : motive t := by
match t with
| .none => assumption
| .more x xs =>
exact cons x (xs ())
def Many.takeAll : Many α → List α
| Many.none => []
/-
invalid pattern, constructor or constant marked with '[match_pattern]' expected
-/
| Many.cons x xs => x :: xs.takeAll
Kyle Miller (Jun 08 2024 at 03:31):
You can't, since fun () => xs
is not a valid pattern.
def Many.takeAll : Many α → List α
| Many.none => []
| Many.more x (fun () => xs) => x :: xs.takeAll
-- ~~~~~~~~~~~~ invalid pattern
Asei Inoue (Jun 08 2024 at 03:32):
impossible? oh no... :sad:
Kyle Miller (Jun 08 2024 at 03:32):
(By the way, for Many.cons_casesOn
, it doesn't make sense giving it @[match_pattern]
. You could, if it's what you want to be the default eliminator for the cases
tactic, use @[cases_eliminator]
instead.)
Kyle Miller (Jun 08 2024 at 03:33):
All @[match_pattern]
does is make it so that match
will unfold a definition while processing the patterns. If the unfolded version doesn't work, then it's no use adding @[match_pattern]
.
Asei Inoue (Jun 08 2024 at 06:01):
@Kyle Miller
You could write an
@[induction_eliminator]
to save you from writingusing myEliminatorTheorem
ininduction xs using myEliminatorTheorem with ...
.
Thank you. but I get an error:
set_option autoImplicit false
variable {α : Type}
inductive Many (α : Type) where
| none : Many α
| more : α → (Unit → Many α) → Many α
@[simp]
theorem Many.fun_simp (xs : Unit → Many α) : (fun _ => xs ()) = xs := by simp
def Many.cons (x : α) (xs : Many α) : Many α :=
.more x (fun () => xs)
/--
info: Many.recOn.{u} {α : Type} {motive : Many α → Sort u} (t : Many α) (none : motive Many.none)
(more : (a : α) → (a_1 : Unit → Many α) → ((a : Unit) → motive (a_1 a)) → motive (Many.more a a_1)) : motive t
-/
#guard_msgs in #check Many.recOn
/-
code generator does not support recursor 'Many.rec' yet, consider using 'match ... with' and/or structural recursion
-/
@[induction_eliminator]
protected def Many.rec_casesOn.{u} {α : Type} {motive : Many α → Sort u} (t : Many α) (none : motive Many.none)
(cons : (a : α) → (b : Many α) → (motive b) → motive (Many.cons a b)) : motive t := by
induction t with
| none => assumption
| more x xs ih =>
specialize ih ()
replace cons := cons x <| xs ()
specialize cons ih
simpa [Many.cons] using cons
Kyle Miller (Jun 08 2024 at 06:05):
Why did you replace your definition of Many.rec_casesOn
if the match
expression from before worked?
Asei Inoue (Jun 08 2024 at 06:10):
Why did you replace your definition of
Many.rec_casesOn
if thematch
expression from before worked?
Sorry I don't understand the intension of your question. what is the "match
expression from before worked"?
But I just want to try induction_eliminator
, I don't expect the proof to work with it.
Kyle Miller (Jun 08 2024 at 06:12):
My suggestion earlier was to replace @[match_pattern]
with @[cases_eliminator]
. There is no need to change the body of the definition, and as you saw, using induction
for the body makes it become not compilable.
@[cases_eliminator]
protected def Many.cons_casesOn.{u} {α : Type} {motive : Many α → Sort u} (t : Many α) (none : motive Many.none)
(cons : (a : α) → (b : Many α) → motive (Many.cons a b)) : motive t := by
match t with
| .none => assumption
| .more x xs =>
exact cons x (xs ())
Kyle Miller (Jun 08 2024 at 06:14):
(Rephrasing "Why did you replace your definition of Many.rec_casesOn
if the match
expression from before worked?" in clearer language: "If it worked to use a match
expression, why did you replace the definition to use induction
?")
Asei Inoue (Jun 08 2024 at 06:17):
@Kyle Miller
why are you talking about cases_eliminator
? I think we are talking about induction_eliminator
.
Kyle Miller (Jun 08 2024 at 06:18):
By the way, the issue with using the induction
or cases
tactic in a def
is that these make use of eliminators for the type, and eliminators do not have compiled code, leading to the "code generator does not support recursor" error.
Kyle Miller (Jun 08 2024 at 06:19):
I'm talking about cases_eliminator
because your Many.cons_casesOn
looks like a cases
eliminator. It has no induction hypothesis in cons
.
Kyle Miller (Jun 08 2024 at 06:19):
(Plus, you named it casesOn
.)
Asei Inoue (Jun 08 2024 at 06:20):
oh... I made a huge naming mistake
Asei Inoue (Jun 08 2024 at 06:32):
I get an error again.
set_option autoImplicit false
variable {α : Type}
inductive Many (α : Type) where
| none : Many α
| more : α → (Unit → Many α) → Many α
@[simp] theorem Many.fun_simp (xs : Unit → Many α) : (fun _ => xs ()) = xs := by simp
def Many.cons (x : α) (xs : Many α) : Many α :=
.more x (fun () => xs)
/-
unexpected eliminator resulting type
motive x.1
-/
@[induction_eliminator]
protected def Many.cons_recOn.{u} {α : Type} {motive : Many α → Sort u} (t : Many α) (none : motive Many.none)
(cons : (a : α) → (b : Many α) → (motive b) → motive (Many.cons a b)) : motive t := by
match t with
| .none => assumption
| .more x xs =>
have ih := Many.cons_recOn (xs ()) (by assumption) cons
replace cons := (cons x <| xs ()) ih
simp [Many.cons] at cons
assumption
done
Eric Wieser (Jun 08 2024 at 07:59):
Kyle Miller said:
I'm talking about
cases_eliminator
because yourMany.cons_casesOn
looks like acases
eliminator. It has no induction hypothesis incons
.
So far in mathlib we've been using these two attributes together. On types where there is no induction going on, is this the morally correct approach?
Eric Wieser (Jun 08 2024 at 08:01):
Alternatively, should induction x
be a lint warning if x : A × B
or some other type where recOn and casesOn coincide?
Asei Inoue (Jun 08 2024 at 08:30):
so is it impossible to write induction_eliminator lemma for Many?
Eric Wieser (Jun 08 2024 at 09:03):
No, it just doesn't like the arguments in the order you have
Eric Wieser (Jun 08 2024 at 09:04):
Here's a working version:
@[elab_as_elim, induction_eliminator]
protected def Many.consRec.{u} {α : Type} {motive : Many α → Sort u} (none : motive Many.none)
(cons : (a : α) → (b : Many α) → (motive b) → motive (Many.cons a b)) : (t : Many α) → motive t
| .none => none
| .more x xs => cons x (xs ()) (Many.consRec none cons (xs ()))
Eric Wieser (Jun 08 2024 at 09:04):
The only required change was moving t
to be the last argument
Asei Inoue (Jun 08 2024 at 09:18):
@Eric Wieser Thank you!!
Last updated: May 02 2025 at 03:31 UTC