Hatena::Grouphaskell

猫とC#について書く代わりにHaskellとF#について書くmatarilloの日記 このページをアンテナに追加 RSSフィード

2015-12-09

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

| 23:00 | 多相リテラルはないけど、演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と - 猫とC#について書く代わりにHaskellとF#について書くmatarilloの日記 のブックマークコメント

この記事はF# Advent Calendar 2015の9日目の記事です。

記事の発端は、id:m-hiyama さんの3つの記事です。

お手軽で実用的なジェネリックスへの道は遠い - 檜山正幸のキマイラ飼育記

コンピュータは「掛け算は足し算とする」を理解できるか - 檜山正幸のキマイラ飼育記

ハイコンテキストな定数・記号の解釈 - 檜山正幸のキマイラ飼育記

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