ext
ext
は、外延性(extensionality)を使うタクティクです。外延性とは、「同じものから作られているものは同じである」という主張のことです。たとえば、「2つの関数 f g : A → B
があるとき ∀ a : A, f a = g a
ならば f = g
」というのは外延性の一種で、関数外延性(functional extensionality) と呼ばれます。
example {A B : Type} (f g : A → B) (h : ∀ a : A, f a = g a) : f = g := by
-- `x : A` を取って外延性を使用する
ext x
-- ゴールが `f x = g x` に変わる
guard_target =ₛ f x = g x
apply h
カスタマイズ
特定の型の外延性を登録し、ext
タクティクで使用できるようにするには、外延性を述べた命題に [ext]
属性を付与します。
universe u
/-- `α` を全体集合とする集合の全体。別の言い方をすれば、`α` のベキ集合。
`α` の部分集合と、`α` 上の述語を同一視している。-/
def Set (α : Type u) := α → Prop
namespace Set
variable {α : Type u}
/-- `x : α` が `s : Set α` の要素であるという命題。-/
def Mem (s : Set α) (x : α) : Prop := s x
/-- 集合らしく `s x` を `x ∈ s` と書けるようにする -/
instance : Membership α (Set α) := ⟨Mem⟩
/-- 集合の外延性。同じ要素からなる集合は等しい -/
theorem ext {a b : Set α} (h : ∀ x, x ∈ a ↔ x ∈ b) : a = b := by
-- 関数外延性を使う
apply funext
intro x
rw [show a x ↔ b x from h x]
example {a b : Set α} (h : ∀ x, x ∈ a ↔ x ∈ b) : a = b := by
-- 最初は使えない
fail_if_success ext x
sorry
-- `[ext]` 属性を付与
attribute [ext] Set.ext
example {a b : Set α} (h : ∀ x, x ∈ a ↔ x ∈ b) : a = b := by
-- ext タクティクが使えるようになった!
ext x
apply h
end Set
構造体に対する [ext] 属性
[ext]
属性は構造体に対しても与えることができます。このとき、その構造体に対して自動的に .ext
と .ext_iff
の2つの定理が生成されます。
variable {α : Type}
structure Point (α : Type) where
x : α
y : α
-- 最初は存在しない
#check_failure Point.ext
#check_failure Point.ext_iff
-- `Point` に `[ext]` 属性を与える
attribute [ext] Point
-- 自動生成された定理
-- 各フィールドの値が等しければ、2つの `Point` は等しいという主張
#check (Point.ext : ∀{x y : Point α}, x.x = y.x → x.y = y.y → x = y)
-- 自動生成された定理その2
-- 2つの `Point` の点が等しいことは、各フィールドの値が等しいことと同値
#check (Point.ext_iff : ∀{x y : Point α}, x = y ↔ x.x = y.x ∧ x.y = y.y)
これにより、構造体に対して ext
タクティクが使用できるようになります。
structure Foo where
x : Nat
y : Nat
example (p q : Foo) (hx : p.x = q.x) (hy : p.y = q.y) : p = q := by
-- 最初は ext タクティクが使えない
fail_if_success ext
sorry
-- `Foo` に `[ext]` 属性を与える
attribute [ext] Foo
example (p q : Foo) (hx : p.x = q.x) (hy : p.y = q.y) : p = q := by
-- ext タクティクが使えるようになった!
ext
· exact hx
· exact hy