Zulip Chat Archive

Stream: new members

Topic: Is it possible to do rw and simp in term mode?


Ching-Tsun Chou (Feb 14 2025 at 23:41):

Is it possible to transform a term using rw and/or simp in term mode? I need to construct a function in which I want to use Fintype.card_coe to simplify a term.

Aaron Liu (Feb 14 2025 at 23:54):

You can enter tactic mode with by, then rw or simp and go back to term mode with exact, but I don't recommend it. These tactics are not meant to generate data, and you could have a bad time proving stuff about your function. There are better ways, depending on what exactly you want to rewrite. For example, docs#Fin.cast lets you rewrite the argument of a Fin without introducing Eq.mpr into your function definition at the term level.

Matt Diamond (Feb 15 2025 at 00:43):

also remember that every equality h is also two functions, one forward (h.mp) and one backward (h.mpr)... you don't need to rewrite to take advantage of an equality

Ching-Tsun Chou (Feb 15 2025 at 00:48):

The term I want to rewrite is a subterm of a bigger term

Aaron Liu (Feb 15 2025 at 00:56):

What is the type you are performing the rewrite in?

Aaron Liu (Feb 15 2025 at 01:03):

This would be much easier if you give a #mwe

Aaron Liu (Feb 15 2025 at 02:24):

Then I wouldn't have to ask so many questions

Ching-Tsun Chou (Feb 15 2025 at 03:05):

I'm trying to fix the failures on lines 100 and 107 of LeanCamCombi/ProbLYM.lean at this branch:
https://github.com/YaelDillies/LeanCamCombi/tree/personal/ctchou/prob-lym-OLD-1
Note, however, that I may decide to work around the problem rather than meeting it head-on.

Ching-Tsun Chou (Feb 15 2025 at 03:13):

The failures are caused by changing the definition of NumberingOn on line 46. (The old definition is on the following, commented out line.) The crux of the problem is this: Previously NumberingOn s is definitionally equal to {x // x ∈ s} ≃ Fin s.card. Now it is definitionally equal to {x // x ∈ s} ≃ Fin (Fintype.card { x // x ∈ s}). In the tactic mode, I can just rw or simp using the theorem Fintype.card_coe. (The top commit of the branch shows some fixes I was able to make this way.). But everything becomes a pain in the term mode.

Aaron Liu (Feb 15 2025 at 03:29):

Just docs#Equiv.trans with docs#finCongr.

Ching-Tsun Chou (Feb 15 2025 at 03:52):

I think I'm going to prove the equivalence of the old and new definitions at the top level and reuse the old code, rather than fixing each failure separately. The term mode is too painful to work with and very hard to read.

suhr (Feb 15 2025 at 07:33):

You can use eq ▸ t to rewrite t by eq in term mode.

suhr (Feb 15 2025 at 07:41):

If a relation is transitive, you can use calc to chain it.

The term mode is too painful to work with and very hard to read.

The term mode is perfectly fine if you know how to use it. I would prefer it over tactic mode if there was a term mode version of refine.

Aaron Liu (Feb 15 2025 at 16:57):

I think it's fine to use refine to create data too, it isn't doing anything too complicated and what you type is what you get.

Yaël Dillies (Feb 15 2025 at 17:00):

suhr said:

I would prefer it over tactic mode if there was a term mode version of refine.

The term-mode version of refine is... term-mode. I'm not sure I understand what you mean

suhr (Feb 16 2025 at 08:08):

Here's an example of a lemma using refine:

def lt_wf (n: Nat): Acc Nat.lt n := by
  refine n.recOn (Acc.intro 0 ?_) ?_
  · intro y (h: y < 0)
    exact absurd h (not_succ_le_zero y)
  · intro n (an: Acc Nat.lt n)
    suffices ih: m, m < n.succ  Acc Nat.lt m from Acc.intro n.succ ih
    intro m h
    have elt: m = n  m < n := eq_or_lt_of_le (le_of_succ_le_succ h)
    exact elt.elim
      (λ(e: m = n) => e.symm  an)
      (λ(l: m < n) => Acc.inv an l)

This is what a term-mode refine would look like:

def lt_wf (n: Nat): Acc Nat.lt n :=
  refine n.recOn (Acc.intro 0 g1) g2 with
  | g1 => λy (h: y < 0) =>
    absurd h (not_succ_le_zero y)
  | g2 => λn (an: Acc Nat.lt n) =>
    suffices ih: m, m < n.succ  Acc Nat.lt m from Acc.intro n.succ ih
    λm h =>
      have elt: m = n  m < n := eq_or_lt_of_le (le_of_succ_le_succ h)
      elt.elim
        (λ(e: m = n) => e.symm  an)
        (λ(l: m < n) => Acc.inv an l)

refine can produce many goals, so you need a syntax that allows to specify several values.

suhr (Feb 16 2025 at 08:15):

Some languages like Haskell or Agda have where expressions, which work essentially the same way.

Ruben Van de Velde (Feb 16 2025 at 08:19):

Lean has where expressions

Kyle Miller (Feb 16 2025 at 08:19):

import Mathlib

open Nat

def lt_wf (n: Nat): Acc Nat.lt n :=
  n.recOn (Acc.intro 0 g1) g2
where
  g1 := λy (h: y < 0) =>
    absurd h (not_succ_le_zero y)
  g2 := λn (an: Acc Nat.lt n) =>
    suffices ih: m, m < n.succ  Acc Nat.lt m from Acc.intro n.succ ih
    λm h =>
      have elt: m = n  m < n := eq_or_lt_of_le (le_of_succ_le_succ h)
      elt.elim
        (λ(e: m = n) => e.symm  an)
        (λ(l: m < n) => Acc.inv an l)

suhr (Feb 16 2025 at 08:23):

Oh, that's nice. Is where a part of def or you can use it freely in any expression?

Kyle Miller (Feb 16 2025 at 08:30):

It's part of def/theorem

Kyle Miller (Feb 16 2025 at 08:30):

This is syntax sugar for let rec

suhr (Feb 16 2025 at 08:32):

Which makes it much less useful unfortunately, since you can't do nesting. For example, this does not work:

example: Nat := a + a
where
  a := b + b
  where
    b := 3

Aaron Liu (Feb 16 2025 at 14:11):

Does this work for you?

example: Nat := a + a
where
  a := b + b
  b := 3

suhr (Feb 16 2025 at 14:38):

Not quite, since nesting is essential for a complex proof. where in Lean is just not as flexible as refine.


Last updated: May 02 2025 at 03:31 UTC