2017-03-11
情報隠蔽とモジュールとシグネチャファイル (F# Advent Calendar 2016)
F# | |
いまさらですが、2016年12月のF# Advent Calendar記事の締め切りに間に合わなかったこともあり、アクセス数が少ないので、ここで再紹介します。
シグネチャファイルを書くことで、型の実装を隠蔽する方法について書きました。
……といいつつ、記事のほとんどは、横浜へなちょこプログラミング勉強会さんによるコーディング問題
五角形の世界であなたは過去の自分に出会う 横へな2016.10.30 問題
の回答になっています。 ^^
コードの説明というより、解法の説明が長いです。
2015-12-09
多相リテラルはないけど、演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と
F# | |
この記事はF# Advent Calendar 2015の9日目の記事です。
記事の発端は、id:m-hiyama さんの3つの記事です。
お手軽で実用的なジェネリックスへの道は遠い - 檜山正幸のキマイラ飼育記 (はてなBlog)
コンピュータは「掛け算は足し算とする」を理解できるか - 檜山正幸のキマイラ飼育記 (はてなBlog)
ハイコンテキストな定数・記号の解釈 - 檜山正幸のキマイラ飼育記 (はてなBlog)
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#でなんとか実現できそう、という感じでした。
2015-12-07
演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と
F# | |
(12/8追記: 檜山さんの新しい記事を受けて、別バージョンを書きました。https://gist.github.com/matarillo/d9861bcce64b4b6ae4da 明日には新しいブログエントリーを書くつもりです。)
Re: コンピュータは「掛け算は足し算とする」を理解できるか - 猫とC#について書く代わりにHaskellとF#について書くmatarilloの日記 - haskellの続き。
もともとの コンピュータは「掛け算は足し算とする」を理解できるか - 檜山正幸のキマイラ飼育記 (はてなBlog)に近しいコードに書き直しました。
Q
をプリフィックスとするカスタム数値リテラルを定義してみました。
0Q
と1Q
の扱いをどうするか悩みましたが、実数 0.0
および1.0
からの変換と同じ扱いにしました。
MinPlus半環の単位元が必要な場合は、MinPlus.Zero
およびMinPlus.One
を使う想定です。
この2つが定義されているので、LanguagePrimitives.GenericZero
とLanguagePrimitives.GenericOne
を使うこともできます。といってもインライン関数以外で使ってもそんなにうれしくないですが……
2015-12-02
Re: コンピュータは「掛け算は足し算とする」を理解できるか
F# | |
行列計算はともかくとして、min-plus半環そのものを定義します。
コンピュータは「掛け算は足し算とする」を理解できるか - 檜山正幸のキマイラ飼育記 (はてなBlog)
複数のプリミティブ数値型に対応するには?と読みました。
新しい演算子、たとえば ?+
と?*
を作る方法も考えられますが、まずはジェネリクスで対応。
F#には型クラスがないので、型に応じた計算の関数を引き渡してるのがださいけど、まあ大目に見るとして。
もとの記事のソースをよく読むと、内部的にはdouble
だけでOKだったっぽい。そしたらもっと楽ですね。後で書けたら書く。