/- # \#synth 型クラス `C` と型 `T` があるとき、`#synth C T` は `T` が `C` のインスタンスになっているかチェックします。もしインスタンスでなかった場合にはエラーになります。 ## 型クラスとは 型クラスとは、複数の型に対して共通の機能や実装を提供するものです。具体例を見てみましょう。たとえば逆数は、複数の型に対して定義されています。 -/ import Mathlib.Data.Rat.Defs -- 有理数 --# import Mathlib.Data.Real.Basic -- 実数 --# -- `⁻¹` で逆数を表すことができる #check (1 : ℚ)⁻¹ -- 実数として見ても同じ #check (1 : ℝ)⁻¹ /- 逆数をとる関数 `fun x => x⁻¹` の定義域はどうなっているのでしょうか?定義域を一般の型 `α` に拡張してみて、どうなるか見てみましょう。-/ variable (α : Type) /-⋆-//-- error: failed to synthesize Inv α Additional diagnostic information may be available using the `set_option diagnostics true` command. -/ #guard_msgs in --# #check (_ : α)⁻¹ /- 一般の型に対して逆数は定義できないので、エラーになってしまいました。エラーメッセージで `α` は `Inv` のインスタンスではないと言われています。この `Inv` が型クラスです。`Inv` のインスタンスであるような型 `T` に対しては、逆数関数 `(·)⁻¹ : T → T` が定義できるというわけです。-/ /- ## インスタンスとは 例えば実数 `ℝ` に対して逆数は定義できるだろうと予想されますが、実際 `ℝ` は `Inv` のインスタンスであることが確認できます。 -/ /-⋆-//-- info: Real.instInv -/ #guard_msgs in --# #synth Inv Real /- 自然数 `ℕ` に対しては逆数が定義されていないと予想されますが、実際 `Inv` のインスタンスになっていません。-/ -- エラーになってしまう /-⋆-//-- error: failed to synthesize Inv ℕ Additional diagnostic information may be available using the `set_option diagnostics true` command. -/ #guard_msgs in --# #synth Inv Nat -- Inv のインスタンスになっていない #check_failure (inferInstance : Inv Nat) /- 自分で無理やり `ℕ` を `Inv` のインスタンスにしてみると、通るようになります。ここでは逆数関数を常に `1` になる定数関数としてみましょう。-/ instance : Inv Nat := ⟨fun _ => 1⟩ #synth Inv Nat example : (1 : ℕ)⁻¹ = 1 := by rfl