The transfer tactic #
transfer α → β => tacs turns a goal about α into the equivalent goal about β along an
equivalence e : α ≃ β, then runs tacs on it. The goal is rewritten in place, so closing
the transferred goal closes the original one: nothing has to be transferred back explicitly.
For instance, given instance : TransferEquiv ZFNat ℕ := ⟨ringEquivNat.toEquiv⟩,
example (n m : ZFNat) : n + m = m + n := by
transfer ZFNat → ℕ =>
rw [Nat.add_comm]
The equivalence is found by instance synthesis on TransferEquiv α β. It may also be given
explicitly, either as transfer α → β using e => tacs, or by naming it in place of the two
types, as transfer e => tacs, in which case the direction is read off the type of e. A
bundled isomorphism (≃+*, ≃*, ≃o, anything with an EquivLike instance) is accepted
wherever an equivalence is, and coerced to the equivalence underlying it. Going
the other way, as in transfer e.symm => tacs, only makes sense if transfer_simps holds the
lemmas for that direction: a simp set oriented the wrong way loops.
Transferring proceeds in three steps:
- every hypothesis whose type mentions
αis reverted, and each binder∀ (x : t), _of the resulting goal whose typetis built out ofαis replaced by∀ (y : t[β/α]), _throughEquiv.forall_congr_left, which putsE.symm ywherexused to be. The equivalenceE : t ≃ t[β/α]is built fromeby congruence, so that a functionf : α → αis transferred to a functionβ → β, and so on for the type formerscongrEquivknows about; - the
transfer_simpssimp set, together withne_eqand lemmas lifting equalities and binders along the equivalences at hand, pushes them through the goal until noαis left. The lemmas of that simp set are what describes how the operations ofαare read inβ, e.g.e (a + b) = e a + e b; - the reverted hypotheses are reintroduced under their original names, and
tacsis run on the resulting goal.
Simplification procedure
Equations
- One or more equations did not get rendered due to their size.
Instances For
Simp set used by the transfer tactic to push an equivalence through a goal. Its lemmas
state how the operations of the source type are read in the target type, e.g.
e (a + b) = e a + e b for the equivalence e a goal is transferred along.
Equations
- One or more equations did not get rendered due to their size.
Instances For
TransferEquiv α β bundles an equivalence α ≃ β as a class, so that transfer α → β can
find it by instance synthesis.
The equivalence along which goals are transferred.
Instances
Lemmas used to push equivalences through a goal #
These are an implementation detail of the tactic, but they have to be public: the tactic looks them up by name in the environment of the file it runs in, and a private declaration is not exported to importing modules at all.
Applying Equiv.arrowCongr is conjugating.
Applying the inverse of Equiv.arrowCongr is conjugating the other way round. This is
Equiv.arrowCongr_symm followed by arrowCongr_apply, but as a single step: rewriting with
Equiv.arrowCongr_symm alone would break the E (E.symm x) pattern that collapses an
equation between functions.
Iterating a conjugated function is conjugating the iterate: this is what makes a statement
about f^[n] travel, f being a binder of type α → α.
Equiv.forall_congr_left, with p explicit so that it can be used as a simp lemma.
Transporting the types of the binders #
The tactic itself #
transfer α → β => tacs transfers the goal along an equivalence α ≃ β and runs tacs on the
transferred goal, which now talks about β instead of α:
example (n m : ZFNat) : n + m = m + n := by
transfer ZFNat → ℕ =>
rw [Nat.add_comm]
The equivalence is synthesized from a TransferEquiv α β instance, or given explicitly by
transfer α → β using e => tacs. Passing the equivalence alone, as in transfer e => tacs, is
also accepted: the direction is then read off the type of e. In both cases e may be a
bundled isomorphism, such as a ≃+* or a ≃o.
Equations
- One or more equations did not get rendered due to their size.