用語のうち曖昧だった部分を整理した。お勉強です。まちがっていたらマサカリをください。著者はCSの学位を持たないかけだしです。
多相(多態)(polymorphism)
- 関数とかが引数の型によってさまざまな振舞いをすること
- より厳密には、値(関数を含む)が型を取るとき、それは多相的(polymorphic)である
- 関数じゃない値が型を取るなんてことあるのかあ?→Listとか……
- より厳密には、値(関数を含む)が型を取るとき、それは多相的(polymorphic)である
- OOPの文脈では多態と呼ばれるが、Haskellまわりでは多相と呼ばれる
- アドホック多相とパラメトリック多相とがある
パラメトリック多相(parametric polymorphism)
- Scalaでいうところの型パラメータで実現できるやつ。パラメータをひっつけて、様々な型を取れるようにする。
- パラメータ多相と同じ。
- 独習Scalazによれば(Haskell Wikiの孫引きであるが)「パラメータ多相 (parametric polymorphism) とは、ある値の型が 1つもしくは複数の (制限の無い) 型変数を含むことを指し、その値は型変数を具象型によって置換することによって得られる型ならどれでも採用することができる。」
アドホック多相(ad-hoc polymorphism)
- Scalaでいうところの、型クラスで既存の型に共通した振舞いをひっつけたりするのにあたりそう
- 本物のプログラマはHaskellを使うによれば「Numクラスで定義されている+演算子などのように,型によって変わる振る舞いを型クラスなどを通して関数に付け足すことで発生する多相性」のこと
- Rubyではよそから振舞いをポン付けできるのでやりやすいが、Scalaでは暗黙的な変換を駆使して実現する。
派生型(subtyping)多相
- OOPの文脈では継承によって(FPの文脈ではどうするのかはよくわからない)、より特定の型に振舞いを定義することでさまざまな振舞いをさせること
- 当然、継承関係になければ使うことができない
パラメータ化された型(parameterized types)
- Wikipediaのジェネリックプログラミングに登場した
- こちらはパラメータがついた型そのものを指す?
- パラメトリック多相は値についての言葉?
型クラス
- ありていに言えば型のクラス(分類)であり、それ以上の実装に踏み込んだ意味合いは本来はない(はず)
- したがって「Implicitを使って型を変換し、ad-hoc多相を実現するのが型クラスだよ」という定義は誤り(のはず)
- OOPでいうクラスとはまったく無関係なので忘れること。本来のクラス(分類)という意味。
- 様々な型は「表示できる」「同一性の比較ができる」といった特性があるが、これを型クラス(e.g.
Show
,Eq
)としてまとめている - すごいH本によれば、そのような特性を満たすような型を「型クラスのインスタンスである型」というふうに表現し、インスタンスは型クラスの特性(e.g. 表示できる)を実際に実装する
- 型クラスを定義してそのインスタンスを実装するという手法で、ad-hoc多相を実現できる
- ある機能について最小限の要請と実装をする(加算さえできればよい全ての型、といった)部品と捉えることができる
- 型クラスは性質の記述である
Scalaz / Shapeless / Cats
- Scalaのライブラリ
- 便利な機能を提供するが、どれも型クラスとそのインスタンスを実装し、アドホック多相を活用したジェネリックプログラミングを支援するようにできている。
- 導入するとコンパイル時間が爆発することで知られているが、impilcit parameterの解決によるもの。
- ShapelessはHaskellのScrap your boilerplateライブラリをportしたもの。
- CatsはScalazよりも後発でありなんか色々改善されているらしい。
- Scalazは日本語資料が豊富。
〆
なんとなく頭の中が整理された気がする。型クラスとかモナドとか、こういったバズワードめいているけれど地に足のついた定義があまり見当らない、みたいな概念ってどうしたらいいのか。実際はきっちりとした定義があるのだろうけれど、数学の教養が必要そうなので大変。
元はといえばHaskellのExtensible Recordsを同僚がScalaでやっているのを見て、こういうScalaでやるパターン(実装方法はHaslkellのものとは違うようだった)ってなんか名前あるんですか、と聞いたのがはじまり。