各言語でtype classesを実装する際に使いそうな道具とか
現時点における GHC、Scala、F#、Java の type classes 実装に使う道具比較をメモしておきます。
言語比較したいわけではなく、論争を繰り広げたいわけでもないのであしからず。
あとてきとーに書いてる感は否めないので、間違っている言葉、表現、概念などあれば適宜突込みをお願いします。
高階型
F# や Java に関しては以下の記事を参照してください。
JavaでFree Monad - scalaとか・・・ F# で高階型のエミュレーション - pocketberserkerの爆走
ランクN多相的な何か
末尾再帰最適化
- GHC: よく知らない(そもそも lazy evaluation だし…)
- Scala: あり。 tailrec annotation をつけておくと末部再帰になっていない場合コンパイルエラー。
- F#: あり。次のバージョンあたりで Scala の tailrec annotation みたいな機能追加したいねとか言っていたような…
- Java: なし
型クラスのインスタンス作成
表現が思いつかなかった…とりあえず Maybe での例
-- GHC instance Monad Maybe where ...
// scalaz の Maybe での例 new Monad[Maybe] {
// F# type Option = Z { new Monad<Option.Z>
F# の場合、型パラメータの制約に hoge メソッドを持つ、とかできるので、高階型をエミュレーションしない場合はこの書き方にならない。 が、あれを説明するのは面倒なので FsControl というライブラリを検索してください。
Java は inner class に型クラスを継承させるのがやりやすい、だったかな?
型引数が2つある場合
- GHC: Monad (Free f) とかやれば書ける
- Scala: Monad[({type f[x] = Free[S, x]})#f]
- F#: 型を握りつぶすか、Option.Zにしておいてメソッドを呼び出したときに型パラメータを指定する
- Java: ワイルドカードを使う
Scalaは今後 type lambdas というシンタックスシュガーが入るかもしれない?
このあたりは F# が不利。 型をいい感じにできるのはもしかしたら type erasure 方式の利点かもしれない。
これと
これとかの比較だと、F# は型が残る上に変位指定ができない(できるならだれか教えてください)から、下手に obj も使えなくて悲しいことになっていたりします。 Java版はそのあたりすっぱり割り切っている。
型推論
これに関してはあまり書きたくない…。
どの言語にもあるけど、どこまで推論されるかは言語次第だよ、くらいでいいですかね? (指摘受けそうだなぁ…)
型クラスライブラリとか
- GHC: Hackage 調べましょう
- Scala: Scalaz が有名ですね
- FsControl, FSharp.Karma
- Java: Functional Java, highj, free-monad-java
おわりに
variance とか GADTs とか代数的データ型とかパターンマッチとか色々書いていない気がするけれど、気が向いたらで…。
あ、OCaml がないのは書いたことないからです…突っつかれたら勉強します。