今日は関西関数型道場の道場開きに参加した。
直接関係はないのだけど、記念にHaskellとC++の対応について雑感を述べる。
もう少し綺麗にまとめられるといいのだが。
Haskell歴数ヶ月の初心者なので間違いを指摘いただけるとありがたい。
C++のコンセプトについてはBoost Concept Check Libraryに基づいて考える。
- 型の族(class)を定義する、
つまりある性質を持つ型全体を考えるという点で
Haskellの型クラスとC++のコンセプトは同等のアイデア - とはいえ、
CopyAssignable
,Moveassignable
といった基本的なコンセプトは
C++の特徴で、Haskellの型クラスに対応するものがある訳ではない。
これはプログラミングモデル(オブジェクト指向 or 関数型)の違いに起因する。 - これはC++のコンセプトの実装の問題で未解決だが、
Boostの実装では基本的にstatic_assert
をによってコンセプトを満している事を要請する。
つまり関数やクラスの定義時において制約を要請する。
他方Haskellでは型演算時の制約として導入する。
C++11の時の提案ではHaskellにだいぶ近かった。 - C++がSFINAE等を駆使してライブラリとしてコンセプトを実装している一方、
Haskellは言語仕様として持っている。 - 型のsignatureを制約する(特定の関数を適用できなければならない)という点で、
Haskellの型クラスとC++やJavaのインターフェイスは同じ目的を持っていると言える。
上述したようなC++特有のメモリの扱いに関するコンセプトがHaskellには必要ないので、
型に対する制約とはほとんど、その型がある関数の引数となれるかとなる。 - 型クラス、あるいはコンセプトによる型のシグネチャの制約は、
実際の型の情報を保持したままである点でインターフェイスと異なる。
インターフェイスを一度通した場合、元の型を回復するには実行時情報(RTTI)が必要となるが、
型クラスでは情報を保持しているのでその必要がない。
C++がマルチパラダイムなせいで、
コンセプトとインターフェイスという別個の同じ目的を持つ機能が言語に含まれている。
さらにC++ではメモリを直接扱う必要があり(copy/move)、
また関数の型が統一されていないせいで、Haskellでは不必要な制約が多数ある。
Haskellでは型に対する制約は型クラスのみで扱えていて、
言語に組込まれているので色々な不都合があらかじめ回避されている。