多相リテラルはないけど、演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と
この記事はF# Advent Calendar 2015の9日目の記事です。
記事の発端は、id:m-hiyama さんの3つの記事です。
http://d.hatena.ne.jp/m-hiyama/20151130/1448843034 http://d.hatena.ne.jp/m-hiyama/20151202/1449016930 http://d.hatena.ne.jp/m-hiyama/20151208/1449544751
3行で無理やりまとめると
- ジェネリクスと演算子オーバーロードと型クラスが便利に使えたらいいなあ。
- C++には演算子オーバーロードがあるし、暗黙の型変換も便利だけど、ユーザー定義リテラルはいまいち。
- 空気を読んでくれる、多相的な定数(数値リテラル)や記号(演算子)があるともっといいのに。
2つ目の記事は、Min-Plus半環という、和と積の定義がちょっとおもしろい代数をネタにしています。
F# は
ジェネリクス | ある |
---|---|
演算子オーバーロード | ある |
型クラス | ない |
ユーザー定義リテラル | ある |
暗黙の型変換 | ない(明示的にしかできない) |
多相的な数値リテラル | ない |
なのだけど、Min-Plus半環のコードを書いてみたらどうなるの?というのをやってみました。
まずは、m-hiyamaさんの2番目の記事のコードを参考に
を入れてみたのが、12/7の記事に載せたコードです。ここに再掲します。
次に、m-hiyamaさんの3番目の記事を参考にして、多相的な数値リテラルはないけれども演算子オーバーロードをたくさん作ってみたらどんな使い勝手になるかを試してみました。
簡単に解説します。
- 演算子
@+
と@*
がMin-Plus半環のための演算子です。これは(?<-
演算子を使うハックによって)int
型、float
型、およびMinPlus
カスタム型を引数にとることができます。 - なお、このハックについては、この記事から始まる5つのエントリーで解説していますので、興味がある人はそちらを読んでください。
main
関数では、シャドーイング機能を使って、+
演算子と*
演算子の実装を@+
と@*
に付け替えています。
ちなみに、fstropical
モジュール(fstropical.fs)では、Min-Plus半環のための演算子として@+
と@*
を使っていますが、ここを+
と*
に置き換えることもできます。すると、fstropical
モジュールをopenするだけで、ファイル全体で+
演算子と*
演算子の動きが置き換わります。
m-hiyamaさんは
僕が名前(記号やリテラルも含む)のオーバーロードに拘るのは、名前の増加に耐えられないからです。 と書いていましたから、
@+
と@*
を使わないコードの方を好まれるかもしれませんね。
というわけで、「空気を読んでくれる演算子」ぐらいならF#でなんとか実現できそう、という感じでした。