|
| 1 | +/- # Functor |
| 2 | +
|
| 3 | +`Functor` は圏論における関手(functor)という概念からその名がある型クラスで、非常に雑な表現をすると、この型クラスを実装した型は「値を包んでいる」ものとして扱うことができます。 |
| 4 | +
|
| 5 | +より詳細には、`f : Type u → Type v` に対して `Functor` はおおむね次のように定義されています。(実際の定義とは異なります) |
| 6 | +-/ |
| 7 | +namespace Hidden --# |
| 8 | +--#-- |
| 9 | +/-- |
| 10 | +info: class Functor.{u, v} : (Type u → Type v) → Type (max (u + 1) v) |
| 11 | +number of parameters: 1 |
| 12 | +constructor: |
| 13 | +Functor.mk : {f : Type u → Type v} → |
| 14 | + ({α β : Type u} → (α → β) → f α → f β) → ({α β : Type u} → α → f β → f α) → Functor f |
| 15 | +fields: |
| 16 | +map : {α β : Type u} → (α → β) → f α → f β |
| 17 | +mapConst : {α β : Type u} → α → f β → f α |
| 18 | +-/ |
| 19 | +#guard_msgs in #print Functor |
| 20 | +--#-- |
| 21 | + |
| 22 | +universe u v |
| 23 | + |
| 24 | +/-- 関手 -/ |
| 25 | +class Functor (f : Type u → Type v) : Type (max (u+1) v) where |
| 26 | + /-- 関数 `g : α → β` を `g* : f α → f β` に変換する -/ |
| 27 | + map : {α β : Type u} → (α → β) → f α → f β |
| 28 | + |
| 29 | +end Hidden --# |
| 30 | +/- つまり、`Functor` のインスタンスは `map` メソッドが使用できます。これは型からわかるように、関数を関数に写す高階関数で、「`f` で包まれる前の関数」から「`f` で包まれた関数」を返します。 -/ |
| 31 | + |
| 32 | +-- `f` は Functor であると仮定 |
| 33 | +variable (f : Type → Type) [Functor f] |
| 34 | + |
| 35 | +-- 関数 `g : α → β` と `x : f α` が与えられたとする |
| 36 | +variable {α β : Type} (g : α → β) |
| 37 | + |
| 38 | +-- 高階関数を返す |
| 39 | +#check (Functor.map (f := f) g : f α → f β) |
| 40 | + |
| 41 | +/- `Functor.map` はよく使われる操作であるため、`<$>` という専用の記法が用意されています。-/ |
| 42 | + |
| 43 | +example (x : f α) : Functor.map g x = g <$> x := rfl |
| 44 | + |
| 45 | +/- ## 典型的なインスタンス |
| 46 | +
|
| 47 | +### List |
| 48 | +`Functor` 型クラスのインスタンスの典型的な例のひとつが `List` です。 |
| 49 | +これにより「リストの各要素に関数を適用する」ための簡単な方法が提供されます。 |
| 50 | +-/ |
| 51 | + |
| 52 | +#guard [1, 2, 3, 4, 5].map (fun x => x * 2) = [2, 4, 6, 8, 10] |
| 53 | + |
| 54 | +/- ### Option |
| 55 | +`Option` も `Functor` 型クラスのインスタンスになっています。 |
| 56 | +これにより「`x? : Option` が `some x` の場合に関数を適用し、`none` なら `none` を返す」という操作のための簡単な方法が提供されます。 |
| 57 | +-/ |
| 58 | + |
| 59 | +#guard (some 2).map (fun x => x * 2) = some 4 |
| 60 | +#guard (none : Option Nat).map (fun x => x * 2) = none |
0 commit comments