読者です 読者をやめる 読者になる 読者になる

各言語でtype classesを実装する際に使いそうな道具とか

現時点における GHCScala、F#、Java の type classes 実装に使う道具比較をメモしておきます。

言語比較したいわけではなく、論争を繰り広げたいわけでもないのであしからず。

あとてきとーに書いてる感は否めないので、間違っている言葉、表現、概念などあれば適宜突込みをお願いします。

高階型

  • GHC: m a
  • Scala: M[A]
  • F#: インターフェース _1<'M, 'A> を用意して擬似的に表現
  • Java: インターフェース _1<M, A> を用意して擬似的に表現

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つある場合

Scalaは今後 type lambdas というシンタックスシュガーが入るかもしれない?

このあたりは F# が不利。 型をいい感じにできるのはもしかしたら type erasure 方式の利点かもしれない。

https://github.com/pocketberserker/FSharp.Karma/blob/9d6aab537793875727f8625acf146e9cbf9931cf/FSharp.Karma/CoYoneda.fs#L13

これと

https://github.com/xuwei-k/free-monad-java/blob/aa7ec1c2897d0982c406524082cd9f8c6fefed37/free/src/main/java/free/Coyoneda.java#L3

これとかの比較だと、F# は型が残る上に変位指定ができない(できるならだれか教えてください)から、下手に obj も使えなくて悲しいことになっていたりします。 Java版はそのあたりすっぱり割り切っている。

型推論

これに関してはあまり書きたくない…。

どの言語にもあるけど、どこまで推論されるかは言語次第だよ、くらいでいいですかね? (指摘受けそうだなぁ…)

型クラスライブラリとか

  • GHC: Hackage 調べましょう
  • Scala: Scalaz が有名ですね
  • FsControl, FSharp.Karma
  • Java: Functional Java, highj, free-monad-java

おわりに

variance とか GADTs とか代数的データ型とかパターンマッチとか色々書いていない気がするけれど、気が向いたらで…。

あ、OCaml がないのは書いたことないからです…突っつかれたら勉強します。