Zulip Chat Archive

Stream: lean4

Topic: Associate value with goal


Marcus Rossel (Nov 24 2021 at 16:48):

I sometimes run into the situation that I have multiple subgoals that can all be solved the same way, except that they require a single different value in an application of a lemma or something.
As an example consider the following (non-mwe) real world example:

theorem ...
  ...
  refine ?ports, ?state, ?reactions, ?reactors -- Splits an (_ ∧ _ ∧ _ ∧ _) into four subgoals

  -- Uses Cmp.prt
  case ports =>
    apply objFor_ext Cmp.prt
    intro j o
    byCases h : Cmp.prt = cmp
    case inl =>
      subst h
      byCases h' : j = i
      case inl =>
        simp [h'] at ht₁ ht₂
        byCases h'' : o = v
        case inl => simp [h'', iff_of_true ht₁ ht₂]
        case inr =>
          exact Iff.intro
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₁⟩)
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₂⟩)
      case inr => simp [(hi₁ j h'), hi₂ j h']
    case inr => simp [(hc₁ Cmp.prt h), hc₂ Cmp.prt h]

  -- Uses Cmp.stv
  case state =>
    apply objFor_ext Cmp.stv
    intro j o
    byCases h : Cmp.stv = cmp
    case inl =>
      subst h
      byCases h' : j = i
      case inl =>
        simp [h'] at ht₁ ht₂
        byCases h'' : o = v
        case inl => simp [h'', iff_of_true ht₁ ht₂]
        case inr =>
          exact Iff.intro
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₁⟩)
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₂⟩)
      case inr => simp [(hi₁ j h'), hi₂ j h']
    case inr => simp [(hc₁ Cmp.stv h), hc₂ Cmp.stv h]

  -- Uses Cmp.rcn
  case reactions =>
    apply objFor_ext Cmp.rcn
    intro j o
    byCases h : Cmp.rcn = cmp
    case inl =>
      subst h
      byCases h' : j = i
      case inl =>
        simp [h'] at ht₁ ht₂
        byCases h'' : o = v
        case inl => simp [h'', iff_of_true ht₁ ht₂]
        case inr =>
          exact Iff.intro
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₁⟩)
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₂⟩)
      case inr => simp [(hi₁ j h'), hi₂ j h']
    case inr => simp [(hc₁ Cmp.rcn h), hc₂ Cmp.rcn h]

  -- Uses Cmp.rtr
  case reactors =>
    apply objFor_ext Cmp.rtr
    intro j o
    byCases h : Cmp.rtr = cmp
    case inl =>
      subst h
      byCases h' : j = i
      case inl =>
        simp [h'] at ht₁ ht₂
        byCases h'' : o = v
        case inl => simp [h'', iff_of_true ht₁ ht₂]
        case inr =>
          exact Iff.intro
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₁⟩)
            (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₂⟩)
      case inr => simp [(hi₁ j h'), hi₂ j h']
    case inr => simp [(hc₁ Cmp.rtr h), hc₂ Cmp.rtr h]

Each of the four subgoals is identical in how it's solved, the only difference being each goal uses a different type of Cmp (Cmp.prt, Cmp.stv, Cmp.rcn and Cmp.rtr).

Is there some way to associate such a value with a goal?
Something like saying for c in #[Cmp.prt. Cmp.stv, Cmp.rcn, Cmp.rtr] { solve the goal using c }.

Mario Carneiro (Nov 24 2021 at 16:51):

It would be pretty easy to do that using runTac, or you can make a local macro tactic

Mario Carneiro (Nov 24 2021 at 16:54):

although, you should really consider making a lemma for that, since it looks like most of it doesn't actually depend on the choice of constructor

Mario Carneiro (Nov 24 2021 at 16:57):

like this:

local macro "foo" e:term : tactic => `((
  apply objFor_ext $e
  intro j o
  byCases h : $e = cmp
  case inl =>
    subst h
    byCases h' : j = i
    case inl =>
      simp [h'] at ht₁ ht₂
      byCases h'' : o = v
      case inl => simp [h'', iff_of_true ht₁ ht₂]
      case inr =>
        exact Iff.intro
          (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₁⟩)
          (λ h => False.elim $ (not_and_self_iff _).mp h'', objFor_unique_obj h ht₂⟩)
    case inr => simp [(hi₁ j h'), hi₂ j h']
  case inr => simp [(hc₁ $e h), hc₂ $e h]))

Last updated: Dec 20 2023 at 11:08 UTC