多相リテラルはないけど、演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と

この記事は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行で無理やりまとめると

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#でなんとか実現できそう、という感じでした。