The Following Are Equivalent (TFAE) #
This file provides the tactics tfae_have and tfae_finish for proving goals of the form
TFAE [P₁, P₂, ...].
Parsing and syntax #
We implement tfae_have in terms of a syntactic have. To support as much of the same syntax as
possible, we recreate the parsers for have, except with the changes necessary for tfae_have.
A tfae_have type specification, e.g. 1 ↔ 3 The numbers refer to the proposition at the
corresponding position in the TFAE goal (starting at 1).
Instances For
The following parsers are similar to those for have in Lean.Parser.Term, but
instead of optType, we use tfaeType := num >> impArrow >> num (as a tfae_have invocation must
always include this specification). Also, we disallow including extra binders, as that makes no
sense in this context; we also include " : " after the binder to avoid breaking tfae_have 1 → 2
syntax (which, unlike have, omits " : ").
tfae_have i → j := t, where the goal is TFAE [P₁, P₂, ...] introduces a hypothesis
tfae_i_to_j : Pᵢ → Pⱼ and proof t to the local context. Note that i and j are
natural number literals (beginning at 1) used as indices to specify the propositions
P₁, P₂, ... that appear in the goal.
Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close
the goal.
All features of have are supported by tfae_have, including naming, matching,
destructuring, and goal creation.
tfae_have i ← j := tadds a hypothesis in the reverse direction, of typePⱼ → Pᵢ.tfae_have i ↔ j := tadds a hypothesis in the both directions, of typePᵢ ↔ Pⱼ.tfae_have hij : i → j := tnames the introduced hypothesishijinstead oftfae_i_to_j.tfae_have i j | p₁ => t₁ | ...matches on the assumptionp : Pᵢ.tfae_have ⟨hij, hji⟩ : i ↔ j := tdestructures the bi-implication intohij : Pᵢ → Pⱼandhji : Pⱼ → Pⱼ.tfae_have i → j := t ?acreates a new goal for?a.
Examples:
example (h : P → R) : TFAE [P, Q, R] := by
tfae_have 1 → 3 := h
-- The resulting context now includes `tfae_1_to_3 : P → R`.
sorry
-- An example of `tfae_have` and `tfae_finish`:
example : TFAE [P, Q, R] := by
tfae_have 1 → 2 := sorry /- proof of P → Q -/
tfae_have 2 → 1 := sorry /- proof of Q → P -/
tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
tfae_finish
-- All features of `have` are supported by `tfae_have`:
example : TFAE [P, Q] := by
-- assert `tfae_1_to_2 : P → Q`:
tfae_have 1 → 2 := sorry
-- assert `hpq : P → Q`:
tfae_have hpq : 1 → 2 := sorry
-- match on `p : P` and prove `Q` via `f p`:
tfae_have 1 → 2
| p => f p
-- assert `pq : P → Q`, `qp : Q → P`:
tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry
-- assert `h : P → Q`; `?a` is a new goal:
tfae_have h : 1 → 2 := f ?a
sorry
Instances For
tfae_finish closes goals of the form TFAE [P₁, P₂, ...] once a sufficient collection
of hypotheses of the form Pᵢ → Pⱼ or Pᵢ ↔ Pⱼ have been introduced to the local context.
tfae_have can be used to conveniently introduce these hypotheses; see tfae_have.
Example:
example : TFAE [P, Q, R] := by
tfae_have 1 → 2 := sorry /- proof of P → Q -/
tfae_have 2 → 1 := sorry /- proof of Q → P -/
tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
tfae_finish
Instances For
Setup #
Extract a list of Prop expressions from an expression of the form TFAE [P₁, P₂, ...] as
long as [P₁, P₂, ...] is an explicit list.
Instances For
Proof construction #
Uses depth-first search to find a path from P to P'.
Prove an implication via depth-first traversal.
Instances For
Generate a proof of Chain (· → ·) P l. We assume P : Prop and l : List Prop, and that l
is an explicit list.
Attempt to prove getLastD l P' → P given an explicit list l.
Attempt to prove a statement of the form TFAE [P₁, P₂, ...].
Instances For
tfae_have components #
Construct a name for a hypothesis introduced by tfae_have.
Instances For
Turn syntax for a given index into a natural number, as long as it lies between 1 and
maxIndex.
Instances For
Tactic implementation #
Accesses the propositions at indices i and j of tfaeList, and constructs the expression
Pi <arr> Pj, which will be the type of our tfae_have hypothesis
Instances For
Deprecated "Goal-style" tfae_have #
This syntax and its implementation, which behaves like "Mathlib have" is deprecated; we preserve
it here to provide graceful deprecation behavior.
Re-enables "goal-style" syntax for tfae_have when true.
tfae_have i → j := t, where the goal is TFAE [P₁, P₂, ...] introduces a hypothesis
tfae_i_to_j : Pᵢ → Pⱼ and proof t to the local context. Note that i and j are
natural number literals (beginning at 1) used as indices to specify the propositions
P₁, P₂, ... that appear in the goal.
Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close
the goal.
All features of have are supported by tfae_have, including naming, matching,
destructuring, and goal creation.
tfae_have i ← j := tadds a hypothesis in the reverse direction, of typePⱼ → Pᵢ.tfae_have i ↔ j := tadds a hypothesis in the both directions, of typePᵢ ↔ Pⱼ.tfae_have hij : i → j := tnames the introduced hypothesishijinstead oftfae_i_to_j.tfae_have i j | p₁ => t₁ | ...matches on the assumptionp : Pᵢ.tfae_have ⟨hij, hji⟩ : i ↔ j := tdestructures the bi-implication intohij : Pᵢ → Pⱼandhji : Pⱼ → Pⱼ.tfae_have i → j := t ?acreates a new goal for?a.
Examples:
example (h : P → R) : TFAE [P, Q, R] := by
tfae_have 1 → 3 := h
-- The resulting context now includes `tfae_1_to_3 : P → R`.
sorry
-- An example of `tfae_have` and `tfae_finish`:
example : TFAE [P, Q, R] := by
tfae_have 1 → 2 := sorry /- proof of P → Q -/
tfae_have 2 → 1 := sorry /- proof of Q → P -/
tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
tfae_finish
-- All features of `have` are supported by `tfae_have`:
example : TFAE [P, Q] := by
-- assert `tfae_1_to_2 : P → Q`:
tfae_have 1 → 2 := sorry
-- assert `hpq : P → Q`:
tfae_have hpq : 1 → 2 := sorry
-- match on `p : P` and prove `Q` via `f p`:
tfae_have 1 → 2
| p => f p
-- assert `pq : P → Q`, `qp : Q → P`:
tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry
-- assert `h : P → Q`; `?a` is a new goal:
tfae_have h : 1 → 2 := f ?a
sorry