use
use
タクティクは、「~を満たす x
が存在する」という命題を示すために、証拠になる x
を具体的に示します。
ゴールが ⊢ ∃ x, P x
のとき、x : X
がローカルコンテキストにあれば、use x
によりゴールが ⊢ P x
に変わります。同時に、P x
が自明な場合は証明が終了します。
import Mathlib.Tactic.Use
import Mathlib.Tactic.Linarith
example {α : Type} (P : α → Prop) (x : α) : ∃ y, P y := by
use x
-- ゴールが `P x` に変わる
guard_target =ₛ P x
sorry
exists との違い
これだけの説明だと exists
タクティクと同じに見えますが、use
タクティクには exists
より優れている点があります。
discharger が指定できる
use
は、証拠を与えた後にゴールを閉じるために使うタクティク(discharger
と呼ばれます)を指定することができます。
example (x : Rat) (h : 3 * x + 6 > 6) : ∃ (y : Rat), y > 0 := by
exists x
linarith
example (x : Rat) (h : 3 * x + 6 > 6) : ∃ (y : Rat), y > 0 := by
-- `discharger` として `linarith` を指定することができる
use (discharger := linarith) x
exists
タクティクにこの構文は存在しません。
open Lean Parser in
/-- `s : String` をパースして `Syntax` の項を得る。`cat` は構文カテゴリ。-/
def parse (cat : Name) (s : String) : MetaM Syntax := do
ofExcept <| runParserCategory (← getEnv) cat s
-- `exists (discharger := linarith)` と書くとパースエラーになる
/-- error: <input>:1:19: expected ')', ',' or ':' -/
#guard_msgs in
#eval parse `tactic "exists (discharger := linarith) 1"
Exists 以外の構造体にも使用できる
exists
は、ゴールの型が Exists
であるという想定をしているため、フィールドの数が3以上であるような構造体に対して使うとエラーになります。
/-- 例示のための構造体。フィールドの数が `Exists` より多い -/
structure Foo where
x : Int
pos : x > 0
sq : x ^ 2 = 9
/-- `Foo` の項を具体的に与える例 -/
example : Foo := ⟨3, by simp, by simp⟩
/--
error: invalid constructor ⟨...⟩, insufficient number of arguments, constructs 'Foo.mk' has #3 explicit fields, but only #2 provided
-/
#guard_msgs in
example : Foo := by
exists 3
しかし、use
タクティクであれば対応することができます。
example : Foo := by
-- 最初のフィールドを `3` で埋めるように指示する
use 3
-- 残りのフィールドは `simp` で証明することができる
all_goals simp
example : Foo := by
-- `discharger` を指定するバージョン
use (discharger := simp) 3