local

local はコマンドをその section の内部でだけ有効にするための構文です.

section foo
  -- local を付けて新しい記法を定義
  local notation " succ' " => Nat.succ

  -- section の中では使用できる
  #check succ'
end foo

-- section を抜けると使えなくなる
#check_failure succ'

section foo
  -- 同じ名前の section を再度開いても使えない
  #check_failure succ'
end foo

コマンドのスコープを namespace の内部に限定するのにも使えます.ただし,下記のコードで示しているように,local で修飾したコマンドの効果は同じ名前空間の中で永続するのではなく, end でその名前空間が閉じられたときに消失します.

namespace hoge
  -- local を付けて新しい記法を定義
  local notation " succ' " => Nat.succ

  -- 定義した namespace の中では使用できる
  #check succ' 2
end hoge

-- namespace の外では使用できない
#check_failure succ' 2

-- 再び同じ名前の namespace をオープンする
namespace hoge
  -- 使用できない!
  #check_failure succ'
end hoge

local で有効範囲を限定できるコマンドには,次のようなものがあります.(以下で全部ではありません)

  • elab, elab_rules
  • macro, macro_rules
  • infix, infil, infixr
  • postfix, postfixl, postfixr
  • prefix
  • notation
  • instance
  • syntax

数が多いためすべての例を挙げることはしませんが,いくつか紹介します.たとえば instance の場合,local を付けて登録したインスタンスがその section の内部限定になります.

inductive MyNat : Type where
  | zero : MyNat
  | succ : MyNat → MyNat

section
  -- local を付けてインスタンスを定義
  local instance : OfNat MyNat 0 where
    ofNat := MyNat.zero

  -- その section の中では使用できる
  #check (0 : MyNat)
end

-- section を抜けると使えなくなる
#check_failure (0 : MyNat)

属性に対する local

属性付与の効果範囲を限定するためには,attribute コマンドを local で修飾するのではなく,attribute コマンドの中で local を使います.

def MyNat.add (n m : MyNat) : MyNat :=
  match m with
  | zero => n
  | succ m => succ (MyNat.add n m)

theorem MyNat.zero_add (n : MyNat) : MyNat.add .zero n = n := by
  induction n with
  | zero => rfl
  | succ n ih => simp [MyNat.add, ih]

section
  -- simp 属性をローカルに付与する
  attribute [local simp] MyNat.zero_add

  -- その section の中では使用できる
  #check (by simp : MyNat.add .zero .zero = .zero)
end

-- section を抜けると simp 補題が利用できなくなる
#check_failure (by simp : MyNat.add .zero .zero = .zero)