Coe

Coe は、型強制(coercion)と呼ばれる仕組みをユーザが定義するための型クラスです。

ある型 T が期待される場所に別の型の項 s : S を見つけると、Lean は型エラーにする前に自動的に型変換を行うことができないか試します。ここで行われる「自動的な型変換」が型強制です。型強制を明示的に指定するには、 記号をつけて ↑x などのようにします。なお 記号については [coe] 属性も深い関係があります。

具体的には Coe S T という型クラスのインスタンスが定義されているとき、型 S の項が型 T に変換されます。

例えば、正の自然数からなる型 Pos を定義したとします。包含関係から Pos → Nat という変換ができるはずです。この変換を関数として定義するだけでは、必要になるごとに毎回書かなければなりませんが、型強制を使うと自動化することができます。

/-- 正の自然数 -/
inductive Pos where
  | one : Pos
  | succ : Pos → Pos

def one : Pos := Pos.one

/-- 階乗関数 -/
def factorial (n : Nat) : Nat :=
  match n with
  | 0 => 1
  | n + 1 => (n + 1) * factorial n

-- `factorial` の引数は `Nat` なのに、`Pos` を渡したのでエラーになる
/--
error: application type mismatch
  factorial one
argument
  one
has type
  Pos : Type
but is expected to have type
  Nat : Type
-/
#guard_msgs (error) in
#check factorial one

/-- `Pos` から `Nat` への変換 -/
def Pos.toNat : Pos → Nat
  | one => 1
  | succ n => n.toNat + 1

-- 明示的に変換すればエラーにならないが、
-- `Pos ⊆ Nat` と見なして自動で変換してほしくなる
#eval factorial <| one.toNat

/-- `Pos` から `Nat` への型強制 -/
instance : Coe Pos Nat where
  coe n := n.toNat

-- 自動的に `Pos` から `Nat` への変換が行われるようになった!
#guard factorial one = 1