HaskellとF#について書くmatarilloの日記(アーカイブ) 2020-03-04T18:55:15+09:00 matarillo Hatena::Blog hatenablog://blog/26006613529988808 情報隠蔽とモジュールとシグネチャファイル (F# Advent Calendar 2016) hatenablog://entry/26006613532098025 2017-03-11T00:49:32+09:00 2020-03-09T04:53:15+09:00 いまさらですが、2016年12月のF# Advent Calendar記事の締め切りに間に合わなかったこともあり、アクセス数が少ないので、ここで再紹介します。 http://qiita.com/matarillo/items/8444db7b97abd29194c2 シグネチャファイルを書くことで、型の実装を隠蔽する方法について書きました。 ……といいつつ、記事のほとんどは、横浜へなちょこプログラミング勉強会さんによるコーディング問題 http://nabetani.sakura.ne.jp/hena/orde09_penwa/ の回答になっています。 ^^ コードの説明というより、解法の説明… <p>いまさらですが、2016年12月のF# Advent Calendar記事の締め切りに間に合わなかったこともあり、アクセス数が少ないので、ここで再紹介します。</p> <p><a href="http://qiita.com/matarillo/items/8444db7b97abd29194c2">http://qiita.com/matarillo/items/8444db7b97abd29194c2</a></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B0%A5%CD%A5%C1%A5%E3">シグネチャ</a>ファイルを書くことで、型の実装を隠蔽する方法について書きました。</p> <p>……といいつつ、記事のほとんどは、横浜へなちょこプログラミング勉強会さんによるコーディング問題 <a href="http://nabetani.sakura.ne.jp/hena/orde09_penwa/">http://nabetani.sakura.ne.jp/hena/orde09_penwa/</a> の回答になっています。 ^^</p> <p>コードの説明というより、解法の説明が長いです。</p> matarillo もしミスチルがF#だったら hatenablog://entry/26006613532098020 2016-09-06T14:49:08+09:00 2020-03-09T04:53:14+09:00 love : 'Ego -> 'Ego -> seq<int> when 'Ego : comparison 記念に。 <pre class="code lang-ocaml" data-lang="ocaml" data-unlink>love : '<span class="synConstant">Ego</span> <span class="synStatement">-&gt;</span> '<span class="synConstant">Ego</span> <span class="synStatement">-&gt;</span> seq<span class="synStatement">&lt;</span><span class="synType">int</span><span class="synStatement">&gt;</span> <span class="synStatement">when</span> '<span class="synConstant">Ego</span> : comparison </pre> <p>記念に。</p> matarillo 多相リテラルはないけど、演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と hatenablog://entry/26006613532098009 2015-12-08T14:00:37+09:00 2020-03-09T04:56:00+09:00 この記事は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++には演算子オーバーロードがあるし、暗黙の型変換も便… <p>この記事は<a href="http://connpass.com/event/22056/">F# Advent Calendar 2015</a>の9日目の記事です。</p> <p>記事の発端は、<a href="https://profile.hatena.ne.jp/m-hiyama/">id:m-hiyama</a> さんの3つの記事です。</p> <p><a href="http://d.hatena.ne.jp/m-hiyama/20151130/1448843034">http://d.hatena.ne.jp/m-hiyama/20151130/1448843034</a> <a href="http://d.hatena.ne.jp/m-hiyama/20151202/1449016930">http://d.hatena.ne.jp/m-hiyama/20151202/1449016930</a> <a href="http://d.hatena.ne.jp/m-hiyama/20151208/1449544751">http://d.hatena.ne.jp/m-hiyama/20151208/1449544751</a></p> <p>3行で無理やりまとめると</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>と型クラスが便利に使えたらいいなあ。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>があるし、暗黙の型変換も便利だけど、ユーザー定義<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>はいまいち。</li> <li>空気を読んでくれる、多相的な定数(数値<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>)や記号(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>)があるともっといいのに。</li> </ul> <p>2つ目の記事は、Min-Plus半環という、和と積の定義がちょっとおもしろい代数をネタにしています。</p> <p>F# は</p> <table> <thead> <tr> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a> </th> <th> ある </th> </tr> </thead> <tbody> <tr> <td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a> </td> <td> ある </td> </tr> <tr> <td> 型クラス </td> <td> ない </td> </tr> <tr> <td> ユーザー定義<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a> </td> <td> ある </td> </tr> <tr> <td> 暗黙の型変換 </td> <td> ない(明示的にしかできない) </td> </tr> <tr> <td> 多相的な数値<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a> </td> <td> ない </td> </tr> </tbody> </table> <p>なのだけど、Min-Plus半環のコードを書いてみたらどうなるの?というのをやってみました。</p> <p>まずは、<a href="http://d.hatena.ne.jp/m-hiyama/20151202/1449016930">m-hiyamaさんの2番目の記事</a>のコードを参考に</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a></li> <li>ユーザー定義<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a></li> <li>明示的な型変換</li> </ul> <p>を入れてみたのが、<a href="http://haskell.g.hatena.ne.jp/matarillo/20151207">12/7の記事</a>に載せたコードです。ここに再掲します。</p> <script src="https://gist.github.com/matarillo/7502d98b8d46f56b4546.js"></script> <p>次に、<a href="http://d.hatena.ne.jp/m-hiyama/20151208/1449544751">m-hiyamaさんの3番目の記事</a>を参考にして、多相的な数値<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>はないけれども<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>をたくさん作ってみたらどんな使い勝手になるかを試してみました。</p> <script src="https://gist.github.com/matarillo/d9861bcce64b4b6ae4da.js"></script> <p>簡単に解説します。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a> <code>@+</code>と<code>@*</code>がMin-Plus半環のための<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>です。これは(<code>?&lt;-</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を使うハックによって)<code>int</code>型、<code>float</code>型、および<code>MinPlus</code>カスタム型を引数にとることができます。</li> <li><ul> <li>なお、このハックについては、<a href="http://haskell.g.hatena.ne.jp/matarillo/20150817/1439787013">この記事</a>から始まる5つのエントリーで解説していますので、興味がある人はそちらを読んでください。</li> </ul> </li> <li><code>main</code>関数では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%E3%A5%C9%A1%BC%A5%A4%A5%F3%A5%B0">シャドーイング</a>機能を使って、<code>+</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>と<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の実装を<code>@+</code>と<code>@*</code>に付け替えています。</li> </ul> <p>ちなみに、<code>fstropical</code>モジュール(fstropical.fs)では、Min-Plus半環のための<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>として<code>@+</code>と<code>@*</code>を使っていますが、ここを<code>+</code>と<code>*</code>に置き換えることもできます。すると、<code>fstropical</code>モジュールをopenするだけで、ファイル全体で<code>+</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>と<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の動きが置き換わります。</p> <p>m-hiyamaさんは</p> <blockquote><p>僕が名前(記号や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>も含む)の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>に拘るのは、名前の増加に耐えられないからです。 と書いていましたから、<code>@+</code>と<code>@*</code>を使わないコードの方を好まれるかもしれませんね。</p></blockquote> <p>というわけで、「空気を読んでくれる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>」ぐらいならF#でなんとか実現できそう、という感じでした。</p> matarillo 演算子オーバーロードとユーザ定義型変換とカスタム数値リテラルとジェネリック単位元と hatenablog://entry/26006613532098005 2015-12-07T10:57:17+09:00 2020-03-09T04:53:13+09:00 (12/8追記: 檜山さんの新しい記事を受けて、別バージョンを書きました。https://gist.github.com/matarillo/d9861bcce64b4b6ae4da 明日には新しいブログエントリーを書くつもりです。) http://haskell.g.hatena.ne.jp/matarillo/20151202/1449027369の続き。 もともとの http://d.hatena.ne.jp/m-hiyama/20151202/1449016930に近しいコードに書き直しました。 Qをプリフィックスとするカスタム数値リテラルを定義してみました。 0Qと1Qの扱いをどうす… <p>(12/8追記: 檜山さんの新しい記事を受けて、別バージョンを書きました。<a href="https://gist.github.com/matarillo/d9861bcce64b4b6ae4da">https://gist.github.com/matarillo/d9861bcce64b4b6ae4da</a> 明日には新しいブログエントリーを書くつもりです。)</p> <p><a href="http://haskell.g.hatena.ne.jp/matarillo/20151202/1449027369">http://haskell.g.hatena.ne.jp/matarillo/20151202/1449027369</a>の続き。</p> <p>もともとの <a href="http://d.hatena.ne.jp/m-hiyama/20151202/1449016930">http://d.hatena.ne.jp/m-hiyama/20151202/1449016930</a>に近しいコードに書き直しました。</p> <p><code>Q</code>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%EA%A5%D5%A5%A3%A5%C3%A5%AF%A5%B9">プリフィックス</a>とするカスタム数値<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>を定義してみました。 <code>0Q</code>と<code>1Q</code>の扱いをどうするか悩みましたが、実数 <code>0.0</code>および<code>1.0</code>からの変換と同じ扱いにしました。</p> <p>MinPlus半環の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%B1%B0%CC%B8%B5">単位元</a>が必要な場合は、<code>MinPlus.Zero</code>および<code>MinPlus.One</code>を使う想定です。</p> <p>この2つが定義されているので、<code>LanguagePrimitives.GenericZero</code>と<code>LanguagePrimitives.GenericOne</code>を使うこともできます。といってもインライン関数以外で使ってもそんなにうれしくないですが……</p> <script src="https://gist.github.com/matarillo/7502d98b8d46f56b4546.js"></script> matarillo Re: コンピュータは「掛け算は足し算とする」を理解できるか hatenablog://entry/26006613532098001 2015-12-02T03:36:09+09:00 2020-03-09T04:53:12+09:00 行列計算はともかくとして、min-plus半環そのものを定義します。 複数のプリミティブ数値型に対応するには?と読みました。 新しい演算子、たとえば ?+と?* を作る方法も考えられますが、まずはジェネリクスで対応。 F#には型クラスがないので、型に応じた計算の関数を引き渡してるのがださいけど、まあ大目に見るとして。 実行結果はIdeoneで見れます。 もとの記事のソースをよく読むと、内部的にはdoubleだけでOKだったっぽい。そしたらもっと楽ですね。後で書けたら書く。 <blockquote><p>行列計算はともかくとして、min-plus半環そのものを定義します。</p></blockquote> <p>複数のプリミティブ数値型に対応するには?と読みました。</p> <p>新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>、たとえば <code>?+</code>と<code>?*</code> を作る方法も考えられますが、まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>で対応。</p> <p>F#には型クラスがないので、型に応じた計算の関数を引き渡してるのがださいけど、まあ大目に見るとして。</p> <script src="https://gist.github.com/matarillo/44d202fce5cfff16d4ca.js"></script> <p><a href="https://ideone.com/FzAgSV">実行結果はIdeoneで見れます</a>。</p> <p>もとの記事のソースをよく読むと、内部的には<code>double</code>だけでOKだったっぽい。そしたらもっと楽ですね。後で書けたら書く。</p> matarillo Re: お手軽で実用的なジェネリックスへの道は遠い hatenablog://entry/26006613532097997 2015-12-01T07:02:06+09:00 2020-03-09T04:53:11+09:00 「TypeScriptジェネリックス:可能性が見えると不満がつのる」において、クラス定義や関数定義に型パラメータを渡せるだけでは、ジェネリック・プログラミングは難しいと述べました。そのときの例題はリストの総和だったのですが、より簡単な累乗(ベキ乗、power)計算を例にしてもう一度問題点を説明します。 最近のプログラミング言語はジェネリックス機能を持っているものが多いですが、言語の進化に伴って後から付けたものがほとんどで、最初からジェネリックスありきで設計したものって、(少なくともメジャーどころでは)ないんじゃないの。ジェネリックスと演算子オーバーロードと型クラスを中核にしたプログラミング言語… <blockquote><p>「TypeScript<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>ス:可能性が見えると不満がつのる」において、クラス定義や関数定義に型パラメータを渡せるだけでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>・プログラミングは難しいと述べました。そのときの例題はリストの総和だったのですが、より簡単な累乗(ベキ乗、power)計算を例にしてもう一度問題点を説明します。</p> <p>最近の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%EC">プログラミング言語</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>ス機能を持っているものが多いですが、言語の進化に伴って後から付けたものがほとんどで、最初から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>スありきで設計したものって、(少なくともメジャーどころでは)ないんじゃないの。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>スと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>と型クラスを中核にした<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%EC">プログラミング言語</a>が出てきたら面白いのにね。</p></blockquote> <p>F# は<a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">TIOBEランキングで31位</a> なのでメジャーどころとは言いにくいところですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>スがあって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>もあって、型クラスはないけどインライン関数の力で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%EA%A5%E2%A1%BC%A5%D5%A5%A3%A5%C3%A5%AF">ポリモーフィック</a>なべき乗を書くことができます。</p> <script src="https://gist.github.com/matarillo/cd9aa111c29573e5576f.js"></script> <p>実行結果は<a href="https://ideone.com/LFqeAg">IdeOne</a>で見ることができます。</p> <p><code><a href="https://msdn.microsoft.com/en-us/library/ee353503.aspx">LanguagePrimitives.GenericOne</a></code>関数は、プリミティブな数値型、もしくは<code>One</code>という名前の静的メンバーが定義されている任意の型を引数にとって、その型の「1」を返すというもの。</p> <p>インライン関数として定義した<code>pow</code>の引数や戻り値の型や型制約を省略しているのでよくわからないかもしれませんが、F#<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>が適切な型や型制約を推論してくれます。</p> <p>たとえば<code>pow</code>の引数<code>x</code>の型については、</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a> <code>*</code> が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>定義されていること</li> <li><code>LanguagePrimitives.GenericOne</code>関数と同じ制約を持つこと、すなわち、プリミティブな数値型、もしくは<code>One</code>という名前の静的メンバーが定義されている任意の型であること</li> </ul> <p>の2つが要請されます。</p> <p>その上で、<code>pow</code>の呼び出し側で、実際にどんな型を引数として渡しているかが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時にチェックされます。今回の例では<code>int</code>型と<code>float</code>型を渡していますが、どちらもプリミティブな数値型であり、<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>定義されているので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>に通ります。</p> <p>「F#すごいじゃん」と思うかもしれませんが、実は注意点があって、F#では<strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>と(多相)インライン関数は別の仕組みなのでシームレスに使うことはできない</strong>というところ。そのあたりのことが<a href="https://msdn.microsoft.com/ja-jp/library/dd548046.aspx">MSDNに書いてあります</a>が、一言でいえば「インライン関数は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>は実行時に型が解決される」という感じです。</p> <p>(追記)ちなみに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>の場合は「staticなんてものはないのだ。シングルトンオブジェクトがあるだけだ。」「型からシングルトンオブジェクトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が決まる仕組みが整備されれば、それが型クラスになるのだ。」という感じの解決法で、(自分で好んで書きたいとはあまり思わないものの)興味深い仕掛けです。</p> matarillo 本質ではない。 hatenablog://entry/26006613532097993 2015-09-28T04:37:43+09:00 2020-03-09T04:53:11+09:00 F# 不況側は何かと「C# はここがダメ!F# はC# よりイイ!」って言うけど、F#の成果がぜんぜんアピールされてないというのは真実。 ほかのはやりの言語は自身をわざわざC# なんかと比較したりしないし、そういうこというのF# ぐらいしかないよね。 F#からWindowsアプリ作るスケルトンはないんですかね 2015-09-13 14:32:18 via TweetDeck F#はVisual Studio的に1st class languageじゃないんだけど、でもそっちを求めるのも個人的には違うなと思ってる。(VSエコシステム的には重要なんだろうけどね)どっちかというとクロプラ方面のほう… <p>F# 不況側は何かと「<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a> はここがダメ!F# は<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a> よりイイ!」って言うけど、F#の成果がぜんぜんアピールされてないというのは真実。</p> <p>ほかのはやりの言語は自身をわざわざ<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a> なんかと比較したりしないし、そういうこというのF# ぐらいしかないよね。</p> <div class="twitter-detail twitter-detail-left"> <div class="twitter-detail-user"> <a class="twitter-user-screen-name" href="http://twitter.com/tanakh"> <img src="https://pbs.twimg.com/profile_images/603918430639521792/zZNtUnXN_normal.png" alt="tanakh" height="48" width="48" this);" > </a> </div> <div class="twitter-detail-tweet"> <p class="twitter-detail-text"> F#から<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>アプリ作るス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B1%A5%EB%A5%C8">ケルト</a>ンはないんですかね </p> <p class="twitter-detail-info"> <a href="http://twitter.com/tanakh/status/642933802352943104" class="twitter-detail-info-permalink"><span class="twitter-detail-info-date">2015-09-13</span> <span class="twitter-detail-info-time">14:32:18</span></a> <span class="twitter-detail-info-source">via <a href="https://about.twitter.com/products/tweetdeck" rel="nofollow">TweetDeck</a></span> </p> </div> </div> <p>F#は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Studio">Visual Studio</a>的に1st class languageじゃないんだけど、でもそっちを求めるのも個人的には違うなと思ってる。(VSエコシステム的には重要なんだろうけどね)どっちかというとクロプラ方面のほうがいいっす。<a class="keyword" href="http://d.hatena.ne.jp/keyword/VS%20Code">VS Code</a>が機能向上しちゃうとそっちも<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a> が出てくるかもしれないけど。</p> matarillo F#のWebアプリケーションフレームワーク hatenablog://entry/26006613532097987 2015-08-30T03:09:36+09:00 2020-03-09T04:53:10+09:00 http://fsharp.org/guides/web/ に載ってる中でちょっと気になったやつをメモ。 Suave.IOはノンブロッキングでクロスプラットフォーム。ほうほう。結構作りこまれてる様子。 http://suave.io/ type SuaveTask<'a> = Async<'a option> type WebPart = HttpContext -> SuaveTask<HttpContext> open Suave open Suave.Http open Suave.Http.Applicatives open Suave.Http.Successful open Sua… <p><a href="http://fsharp.org/guides/web/">http://fsharp.org/guides/web/</a> に載ってる中でちょっと気になったやつをメモ。</p> <p>Suave.IOはノン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%ED%A5%C3%A5%AD%A5%F3%A5%B0">ブロッキング</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a>。ほうほう。結構作りこまれてる様子。 <a href="http://suave.io/">http://suave.io/</a></p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">SuaveTask</span><span class="synStatement">&lt;</span>'a<span class="synStatement">&gt;</span> <span class="synStatement">=</span> <span class="synConstant">Async</span><span class="synStatement">&lt;</span>'a <span class="synType">option</span><span class="synStatement">&gt;</span> <span class="synStatement">type</span> <span class="synConstant">WebPart</span> <span class="synStatement">=</span> <span class="synConstant">HttpContext</span> <span class="synStatement">-&gt;</span> <span class="synConstant">SuaveTask</span><span class="synStatement">&lt;</span><span class="synConstant">HttpContext</span><span class="synStatement">&gt;</span> </pre> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">open</span> <span class="synPreProc">Suave</span> <span class="synStatement">open</span> <span class="synPreProc">Suave.Http</span> <span class="synStatement">open</span> <span class="synPreProc">Suave.Http.Applicatives</span> <span class="synStatement">open</span> <span class="synPreProc">Suave.Http.Successful</span> <span class="synStatement">open</span> <span class="synPreProc">Suave.Web</span> <span class="synStatement">let</span> app <span class="synStatement">=</span> choose <span class="synStatement">[</span> <span class="synConstant">GET</span> <span class="synStatement">&gt;&gt;=</span> choose <span class="synStatement">[</span> path <span class="synConstant">&quot;/hello&quot;</span> <span class="synStatement">&gt;&gt;=</span> <span class="synConstant">OK</span> <span class="synConstant">&quot;Hello GET&quot;</span> path <span class="synConstant">&quot;/goodbye&quot;</span> <span class="synStatement">&gt;&gt;=</span> <span class="synConstant">OK</span> <span class="synConstant">&quot;Good bye GET&quot;</span> <span class="synStatement">]</span> <span class="synConstant">POST</span> <span class="synStatement">&gt;&gt;=</span> choose <span class="synStatement">[</span> path <span class="synConstant">&quot;/hello&quot;</span> <span class="synStatement">&gt;&gt;=</span> <span class="synConstant">OK</span> <span class="synConstant">&quot;Hello POST&quot;</span> path <span class="synConstant">&quot;/goodbye&quot;</span> <span class="synStatement">&gt;&gt;=</span> <span class="synConstant">OK</span> <span class="synConstant">&quot;Good bye POST&quot;</span> <span class="synStatement">]</span> <span class="synStatement">]</span> startWebServer defaultConfig app </pre> <p>Freyaはステートマシン。シンプルっぽい。 <a href="https://github.com/freya-fs/freya">https://github.com/freya-fs/freya</a></p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Freya</span><span class="synStatement">&lt;</span>'a<span class="synStatement">&gt;</span> <span class="synStatement">=</span> <span class="synConstant">FreyaState</span> <span class="synStatement">-&gt;</span> <span class="synConstant">Async</span><span class="synStatement">&lt;</span>'a <span class="synStatement">*</span> <span class="synConstant">FreyaState</span><span class="synStatement">&gt;</span> </pre> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> double x <span class="synStatement">=</span> freya <span class="synStatement">{</span> return x <span class="synStatement">*</span> <span class="synConstant">2</span> <span class="synStatement">}</span> </pre> matarillo 演算子のオーバーロード #5(完結編) hatenablog://entry/26006613532097980 2015-08-30T03:01:04+09:00 2020-03-09T04:53:09+09:00 ちょっと間が空いた。 さて、ここまでを踏まえれば、最初の記事に載せた http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288 はほぼ理解できる。 組み込みのfloatとユーザー定義のvector2の両方で使えるように、2項演算子 *= をオーバーロードしたい しかし、float同士の*=演算を、後付けで定義することができない そこで、以下のハックを使う 演算子オーバーロードのためだけに、新たなユーザー… <p>ちょっと間が空いた。</p> <p>さて、ここまでを踏まえれば、最初の記事に載せた</p> <p><a href="http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288">http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288</a></p> <p>はほぼ理解できる。</p> <ul> <li>組み込みの<code>float</code>とユーザー定義の<code>vector2</code>の両方で使えるように、2項<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a> <code>*=</code> を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>したい</li> <li>しかし、<code>float</code>同士の<code>*=</code>演算を、後付けで定義することができない</li> <li>そこで、以下のハックを使う</li> <li><ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>のためだけに、新たなユーザー定義型 <code>Overloads</code>を定義する</li> </ul> </li> <li><ul> <li>ユーザー定義型 <code>Overloads</code>に、3項<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a> <code>?&lt;-</code>を定義する</li> </ul> </li> <li><ul> <li>その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>は、<code>Overloads</code>型の値を1つ、<code><em>=</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を適用したい型の値を2つ受け取るが、<code>Overloads</code>型の値は捨ててしまい、本来やりたかった<code></em>=</code>演算だけを実装する</li> </ul> </li> <li>以上の準備ができたなら、グローバルレベルでのインライン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>定義で、<code>*=</code>を実装し、<code>Overloads</code>型の<code>?&lt;-</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>にぶん投げる</li> <li><ul> <li><code>Overloads</code>型の値は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>の解決に使われた後は捨てられるので、unit的に値が1つしかない型で十分。よって、<code>Overloads</code>型は値が1つしかない判別共用体として定義してもいい。</li> </ul> </li> </ul> <p>なんとまあ。分かってしまえば何ということはなかった。<code>?&lt;-</code>を使っているのは単にそれが3項<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>だからってだけのようだし、<code>Overloads</code>型が値が1つしかない判別共用体であることにも大きな意味はなかった。</p> matarillo 演算子のオーバーロード #4 hatenablog://entry/26006613532097974 2015-08-24T09:47:59+09:00 2020-03-09T04:53:08+09:00 グローバルレベルで定義された演算子が演算子のオーバーロードを隠してしまう。それはわかった。それならそれで、グローバルレベルで定義された演算子は多相(ジェネリック)にできないのだろうか。 結論から言うとできる。ただし気を付けなければならないことがある。 まず、関数の場合は山かっこ(<および>)を関数名の直後に置ける。 let addCount<'a when 'a :> System.Collections.ICollection> (x: 'a) (y: 'a) = x.Count + y.Count この書き方は演算子ではできない。代わりにこのように書く。 // 演算子の場合はこう書くしかな… <p>グローバルレベルで定義された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>を隠してしまう。それはわかった。それならそれで、グローバルレベルで定義された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>は多相(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>)にできないのだろうか。</p> <p>結論から言うとできる。ただし気を付けなければならないことがある。</p> <p>まず、関数の場合は山かっこ(<code>&lt;</code>および<code>&gt;</code>)を関数名の直後に置ける。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> addCount<span class="synStatement">&lt;</span>'a <span class="synStatement">when</span> 'a :<span class="synStatement">&gt;</span> <span class="synPreProc">System</span>.<span class="synPreProc">Collections</span>.<span class="synConstant">ICollection</span><span class="synStatement">&gt;</span> <span class="synStatement">(</span>x: 'a<span class="synStatement">)</span> <span class="synStatement">(</span>y: 'a<span class="synStatement">)</span> <span class="synStatement">=</span> x.<span class="synConstant">Count</span> + y.<span class="synConstant">Count</span> </pre> <p>この書き方は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>ではできない。代わりにこのように書く。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink>// 演算子の場合はこう書くしかない <span class="synStatement">let</span> <span class="synStatement">(</span>+<span class="synStatement">)</span> <span class="synStatement">(</span>x: 'a<span class="synStatement">)</span> <span class="synStatement">(</span>y: 'a<span class="synStatement">)</span>: <span class="synType">int</span> <span class="synStatement">when</span> 'a :<span class="synStatement">&gt;</span> <span class="synPreProc">System</span>.<span class="synPreProc">Collections</span>.<span class="synConstant">ICollection</span> <span class="synStatement">=</span> x.<span class="synConstant">Count</span> + y.<span class="synConstant">Count</span> // なお関数なら両方の書き方が許される <span class="synStatement">let</span> addCount <span class="synStatement">(</span>x: 'a<span class="synStatement">)</span> <span class="synStatement">(</span>y: 'a<span class="synStatement">)</span>: <span class="synType">int</span> <span class="synStatement">when</span> 'a :<span class="synStatement">&gt;</span> <span class="synPreProc">System</span>.<span class="synPreProc">Collections</span>.<span class="synConstant">ICollection</span> <span class="synStatement">=</span> x.<span class="synConstant">Count</span> + y.<span class="synConstant">Count</span> </pre> <p>こうすれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>ができるのだが、F#の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>は.NETの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%AF%A5%B9">ジェネリクス</a>を基盤にしているから、F#の型制約も基本的にはその範囲でしか書けない。つまり、(new制約や構造体制約は別とすれば)指定したクラスやインターフェースを継承している場合に、その型の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>メソッドが呼び出せる、という程度のことしかできない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>はスタティックメンバー扱いだから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>なメソッドからは呼び出せない。したがって、グローバルレベルで定義された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の実装から呼び出すこともできない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>と一緒である<a href="#f-2bc19e60" name="fn-2bc19e60" title="F#では列挙型制約やデリゲート制約をつけられるが、C#ではできないという違いはある">*1</a>。</p> <p>ただ、F#の強力なところは、インライン関数を使うことでその制限を超えることができることだ。インライン関数は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時に静的に型が解決されるため、明示的なメンバーの制約をかけることで、型階層によらず、また静的メンバーと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>メンバーを問わず、あるメンバーを持っている型が使われることを要請できる。</p> <p>VSで書くといまいちわかりづらいのでF# Intaractiveを使う。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">&gt;</span> <span class="synStatement">let</span> inline <span class="synStatement">(</span>%<span class="synStatement">*)</span> x y <span class="synStatement">=</span> x <span class="synStatement">*</span> y<span class="synStatement">;;</span> <span class="synStatement">val</span> inline <span class="synStatement">(</span> %<span class="synStatement">*</span> <span class="synStatement">)</span> : x: <span class="synStatement">^</span>a <span class="synStatement">-&gt;</span> y: <span class="synStatement">^</span>b <span class="synStatement">-&gt;</span> <span class="synStatement">^</span>c <span class="synStatement">when</span> <span class="synStatement">(</span> <span class="synStatement">^</span>a or <span class="synStatement">^</span>b<span class="synStatement">)</span> : <span class="synStatement">(</span>static member <span class="synStatement">(</span> <span class="synStatement">*</span> <span class="synStatement">)</span> : <span class="synStatement">^</span>a <span class="synStatement">*</span> <span class="synStatement">^</span>b <span class="synStatement">-&gt;</span> <span class="synStatement">^</span>c<span class="synStatement">)</span> </pre> <p><code>%<em></code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の型が、通常の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>型引数で使われる <code>'a</code>や<code>'b</code>ではなく、静的に解決される型を表す <code>^a</code>や<code>^b</code>になっている。<code>%</em></code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を使う際には、左項(<code>x</code>)または右項(<code>y</code>)のどちらかの型に対して<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>が定義されており、もう一方の項の型もその定義に適合するのであれば、どんな型であってもこの新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を適用できる。</p> <p>もちろん、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時にインライン展開(β変換)されるので、通常の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>な型に適用することはできない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>な型は実行時に解決されるものだからである。</p> <p>(続く)</p> <div class="footnote"> <p class="footnote"><a href="#fn-2bc19e60" name="f-2bc19e60" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">F#では列挙型制約やデリゲート制約をつけられるが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>ではできないという違いはある</span></p> </div> matarillo 演算子のオーバーロード #3 hatenablog://entry/26006613532097969 2015-08-22T22:59:15+09:00 2020-03-09T04:53:07+09:00 さて、?<-はいったん置いておいて、演算子のオーバーロード解決を勉強した。 F# の演算子定義は2通りのパターンがある。 1つは(C#と同様に)クラスなどのスタティックメンバーとして書くもの。 type MyRecord = { x: int; y: int } with static member (+) (left: MyRecord, right: MyRecord) = { x = left.x + right.x; y = left.y + right.y } メソッドとして書くので、引数はタプルで受け取る。しかし実際には中置演算子として使える。 もう1つは、グローバルレベルで定義す… <p>さて、<code>?&lt;-</code>はいったん置いておいて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>解決を勉強した。</p> <p>F# の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>定義は2通りのパターンがある。</p> <p>1つは(<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>と同様に)クラスなどのスタティックメンバーとして書くもの。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">MyRecord</span> <span class="synStatement">=</span> <span class="synStatement">{</span> x: <span class="synType">int</span><span class="synStatement">;</span> y: <span class="synType">int</span> <span class="synStatement">}</span> <span class="synStatement">with</span> static member <span class="synStatement">(</span>+<span class="synStatement">)</span> <span class="synStatement">(</span>left: <span class="synConstant">MyRecord</span>, right: <span class="synConstant">MyRecord</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">{</span> x <span class="synStatement">=</span> left.x + right.x<span class="synStatement">;</span> y <span class="synStatement">=</span> left.y + right.y <span class="synStatement">}</span> </pre> <p>メソッドとして書くので、引数はタプルで受け取る。しかし実際には中置<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>として使える。</p> <p>もう1つは、グローバルレベルで定義するもの。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> <span class="synStatement">(</span>+<span class="synStatement">)</span> <span class="synStatement">(</span>left: <span class="synConstant">MyRecord</span><span class="synStatement">)</span> <span class="synStatement">(</span>right: <span class="synConstant">MyRecord</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">{</span> x <span class="synStatement">=</span> left.x + right.x<span class="synStatement">;</span> y <span class="synStatement">=</span> left.y + right.y <span class="synStatement">}</span> </pre> <p>こちらはF#の関数として書くので、引数はタプルにしない。こちらも中置<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>として使える。</p> <p>これらの違いは何かというと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>(多重定義)されるかどうかが違う。</p> <p>グローバルレベルで定義された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>を隠してしまう。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> <span class="synStatement">(</span>+<span class="synStatement">)</span> <span class="synStatement">(</span>left: <span class="synConstant">MyRecord</span><span class="synStatement">)</span> <span class="synStatement">(</span>right: <span class="synConstant">MyRecord</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">{</span> x <span class="synStatement">=</span> left.x + right.x<span class="synStatement">;</span> y <span class="synStatement">=</span> left.y + right.y <span class="synStatement">}</span> <span class="synStatement">let</span> a <span class="synStatement">=</span> <span class="synConstant">1</span> + <span class="synConstant">2</span> // コンパイルエラー。<span class="synConstant">MyRecord</span>型の引数が期待されるところにint型の引数を渡している。 </pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>が期待通りに動作するためには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>はグローバルレベルで定義するのではなく、引数の型のスタティックメンバーとして定義しておかなければならない。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>解決は、まずグローバルレベルの定義を探し、それが見つからなかった場合だけ、引数の型のスタティックメンバーから適切な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>定義を探す、という順番になっているからだ。</p> <p>(続く)</p> matarillo 演算子のオーバーロード #2 hatenablog://entry/26006613532097959 2015-08-17T17:07:35+09:00 2020-03-09T04:53:07+09:00 F#の ?<- 演算子(動的プロパティに値を設定する演算子)はわりとキモいことがわかってきた。 まずはこんな感じでグローバルな演算子を定義してみる。 let (?<-) (d:#IDictionary<'K, 'V>) k v = d.[k] <- v まず、キーとして適当な判別共用体を食わせてみる。 type MyUnion = A | B | C of int let testUnion = let d = new Dictionary<MyUnion, int>() let k = C 12 d.[k] <- 1 d?(k) <- 2 d?(C 12) <- 3 printfn "%A"… <p>F#の <code>?&lt;-</code> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>(動的プロパティに値を設定する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>)はわりとキモいことがわかってきた。</p> <p>まずはこんな感じでグローバルな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を定義してみる。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> <span class="synStatement">(?&lt;-)</span> <span class="synStatement">(</span>d:<span class="synPreProc">#</span><span class="synConstant">IDictionary</span><span class="synStatement">&lt;</span>'<span class="synConstant">K</span>, '<span class="synConstant">V</span><span class="synStatement">&gt;)</span> k v <span class="synStatement">=</span> d.<span class="synStatement">[</span>k<span class="synStatement">]</span> <span class="synStatement">&lt;-</span> v </pre> <p>まず、キーとして適当な判別共用体を食わせてみる。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">MyUnion</span> <span class="synStatement">=</span> <span class="synConstant">A</span> <span class="synStatement">|</span> <span class="synConstant">B</span> <span class="synStatement">|</span> <span class="synConstant">C</span> <span class="synStatement">of</span> <span class="synType">int</span> <span class="synStatement">let</span> testUnion <span class="synStatement">=</span> <span class="synStatement">let</span> d <span class="synStatement">=</span> <span class="synStatement">new</span> <span class="synConstant">Dictionary</span><span class="synStatement">&lt;</span><span class="synConstant">MyUnion</span>, <span class="synType">int</span><span class="synStatement">&gt;</span><span class="synConstant">()</span> <span class="synStatement">let</span> k <span class="synStatement">=</span> <span class="synConstant">C</span> <span class="synConstant">12</span> d.<span class="synStatement">[</span>k<span class="synStatement">]</span> <span class="synStatement">&lt;-</span> <span class="synConstant">1</span> d<span class="synStatement">?(</span><span class="synIdentifier">k</span><span class="synStatement">)</span> <span class="synStatement">&lt;-</span> <span class="synConstant">2</span> d<span class="synStatement">?(</span><span class="synConstant">C</span> <span class="synConstant">12</span><span class="synStatement">)</span> <span class="synStatement">&lt;-</span> <span class="synConstant">3</span> printfn <span class="synConstant">&quot;%A&quot;</span> <span class="synStatement">(</span>d.<span class="synStatement">[</span>k<span class="synStatement">])</span> </pre> <p>出力は想像通り、 <code>3</code> になる。 まあそれはいい。</p> <p>次に、キーとして文字列を食わせてみる。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> testString <span class="synStatement">=</span> <span class="synStatement">let</span> d <span class="synStatement">=</span> <span class="synStatement">new</span> <span class="synConstant">Dictionary</span><span class="synStatement">&lt;</span><span class="synType">string</span>, <span class="synType">int</span><span class="synStatement">&gt;</span><span class="synConstant">()</span> <span class="synStatement">let</span> k <span class="synStatement">=</span> <span class="synConstant">&quot;foo&quot;</span> d.<span class="synStatement">[</span>k<span class="synStatement">]</span> <span class="synStatement">&lt;-</span> <span class="synConstant">1</span> d<span class="synStatement">?(</span><span class="synIdentifier">k</span><span class="synStatement">)</span> <span class="synStatement">&lt;-</span> <span class="synConstant">2</span> d<span class="synStatement">?</span><span class="synIdentifier">foo</span> <span class="synStatement">&lt;-</span> <span class="synConstant">3</span> printfn <span class="synConstant">&quot;%A&quot;</span> <span class="synStatement">(</span>d.<span class="synStatement">[</span>k<span class="synStatement">])</span> </pre> <p>エラーは出ず、出力は <code>3</code> になる。</p> <p><code>d?foo</code> は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>で言うところの<code>dynamic</code>型みたいな感じで、文字列として書いてなくても文字列として<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>されるということのようだ。キモいけど、なんとかわかった。 (続く)</p> matarillo 演算子のオーバーロード #1 hatenablog://entry/26006613532097956 2015-08-17T04:50:13+09:00 2020-03-09T04:53:06+09:00 http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288 F#の ?<- 演算子は「動的プロパティに値を設定する演算子」なんですが、なんでそれがここに? しかも、 type Overloads = Overloads って、値が1つしかない判別共用体ですよね。なんでそれがここに? F#の演算子のことをよくわかっていないことに気づいたので、改めて勉強していこうと思います。 <p><a href="http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288">http://stackoverflow.com/questions/11150947/f-overloaded-operater-with-floats-not-working-with-other-floats/11152288#11152288</a></p> <p>F#の <code>?&lt;-</code> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>は「動的プロパティに値を設定する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>」なんですが、なんでそれがここに? しかも、</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Overloads</span> <span class="synStatement">=</span> <span class="synConstant">Overloads</span> </pre> <p>って、値が1つしかない判別共用体ですよね。なんでそれがここに?</p> <p>F#の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>のことをよくわかっていないことに気づいたので、改めて勉強していこうと思います。</p> matarillo Minority's hello, worldにF#で挑戦 hatenablog://entry/26006613532097947 2015-07-09T03:20:55+09:00 2020-03-09T04:53:04+09:00 CodeIQにMinority's hello, worldという問題が出ていました。 問題が見れなくなっているので引用すると、こういうもの。 ■問題の概要 「hello, world」と出力するプログラムを提出して下さい。 提出されたプログラムで使われている文字を、全挑戦者について集計します。 各文字には「(その文字を利用した挑戦者の人数)の2乗」というポイントが割り当てられます。 提出されたプログラムのポイントは、そのプログラムで使われている文字のポイントの合計となります。 提出コードのポイントが少ない順に順位をつけます。最小ポイントの方が優勝です。 出題者の鍋谷さんによる結果発表と解説が… <p>CodeIQに<a href="https://codeiq.jp/q/1579">Minority's hello, world</a>という問題が出ていました。</p> <p>問題が見れなくなっているので引用すると、こういうもの。</p> <blockquote><p><h4>■問題の概要</h4> 「hello, world」と出力するプログラムを提出して下さい。 提出されたプログラムで使われている文字を、全挑戦者について集計します。 各文字には「(その文字を利用した挑戦者の人数)の2乗」というポイントが割り当てられます。 提出されたプログラムのポイントは、そのプログラムで使われている文字のポイントの合計となります。 提出コードのポイントが少ない順に順位をつけます。最小ポイントの方が優勝です。</p></blockquote> <p>出題者の鍋谷さんによる結果発表と解説がこちら。</p> <p><a href="http://nabetani.sakura.ne.jp/codeiq/hwbattle2/">http://nabetani.sakura.ne.jp/codeiq/hwbattle2/</a></p> <p>で、私はF#で適当に(あまり考えずに)下のようなコードをぶっこんで</p> <pre class="code lang-cs" data-lang="cs" data-unlink>System.Console.Write(<span class="synConstant">&quot;hello, world&quot;</span>) </pre> <p>結果、スコアは29,198点、順位は58位となり、当然上位には入れませんでした。</p> <p>で、ここからが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A1%BC%A5%C9%A5%B4%A5%EB%A5%D5">コードゴルフ</a>。</p> <p>じゃあ、どういうコードだったらもっとスコアが良かった(低くなった)か?ということで再考したのがこちら。</p> <pre class="code lang-cs" data-lang="cs" data-unlink>printf&lt;|<span class="synConstant">&quot;%s&quot;</span>&lt;|<span class="synConstant">&quot;hello,</span><span class="synSpecial">\u0020</span><span class="synConstant">world&quot;</span> </pre> <p>これだと何点取れてたかを計算し直したコードがこちら。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> addCount <span class="synStatement">(</span>xs: <span class="synStatement">(</span><span class="synType">char</span><span class="synStatement">*</span><span class="synType">int</span><span class="synStatement">)</span> seq<span class="synStatement">)</span> <span class="synStatement">(</span>ys: <span class="synStatement">(</span><span class="synType">char</span><span class="synStatement">*</span><span class="synType">int</span><span class="synStatement">)</span> seq<span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synPreProc">Seq</span>.append xs ys <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.groupBy fst <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.map <span class="synStatement">(fun</span> <span class="synStatement">(</span>c,zs<span class="synStatement">)</span> <span class="synStatement">-&gt;</span> c,<span class="synStatement">(</span><span class="synPreProc">Seq</span>.sumBy snd zs<span class="synStatement">))</span> <span class="synStatement">let</span> calc <span class="synStatement">(</span>xs: <span class="synStatement">(</span><span class="synType">char</span><span class="synStatement">*</span><span class="synType">int</span><span class="synStatement">)</span> seq<span class="synStatement">)</span> <span class="synStatement">(</span>ys: <span class="synType">char</span> seq<span class="synStatement">)</span> <span class="synStatement">=</span> ys <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.map <span class="synStatement">(fun</span> c <span class="synStatement">-&gt;</span> <span class="synPreProc">Seq</span>.find <span class="synStatement">(fun</span> <span class="synStatement">(</span>c',<span class="synStatement">_)</span> <span class="synStatement">-&gt;</span> c<span class="synStatement">=</span>c'<span class="synStatement">)</span> xs<span class="synStatement">)</span> <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.sumBy <span class="synStatement">(fun</span> <span class="synStatement">(_</span>,v<span class="synStatement">)</span> <span class="synStatement">-&gt;</span> v<span class="synStatement">*</span>v<span class="synStatement">)</span> <span class="synStatement">[&lt;</span><span class="synConstant">EntryPoint</span><span class="synStatement">&gt;]</span> <span class="synStatement">let</span> main argv <span class="synStatement">=</span> <span class="synStatement">let</span> othersCount <span class="synStatement">=</span> <span class="synStatement">[(</span><span class="synConstant">' '</span>, <span class="synConstant">42</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'!'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'&quot;'</span>, <span class="synConstant">24</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'#'</span>, <span class="synConstant">10</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'$'</span>, <span class="synConstant">12</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'%'</span>, <span class="synConstant">10</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'&amp;'</span>, <span class="synConstant">10</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'\''</span>, <span class="synConstant">19</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'('</span>, <span class="synConstant">28</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">')'</span>, <span class="synConstant">26</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'*'</span>, <span class="synConstant">6</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'+'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">','</span>, <span class="synConstant">36</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'-'</span>, <span class="synConstant">17</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'.'</span>, <span class="synConstant">24</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'/'</span>, <span class="synConstant">7</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'0'</span>, <span class="synConstant">17</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'1'</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'2'</span>, <span class="synConstant">15</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'3'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'4'</span>, <span class="synConstant">18</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'5'</span>, <span class="synConstant">14</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'6'</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'7'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'8'</span>, <span class="synConstant">12</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'9'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">':'</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">';'</span>, <span class="synConstant">19</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'&lt;'</span>, <span class="synConstant">20</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'='</span>, <span class="synConstant">16</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'&gt;'</span>, <span class="synConstant">15</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'?'</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'@'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'A'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'B'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'C'</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'D'</span>, <span class="synConstant">13</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'E'</span>, <span class="synConstant">16</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'F'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'G'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'H'</span>, <span class="synConstant">16</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'I'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'J'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'K'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'L'</span>, <span class="synConstant">16</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'M'</span>, <span class="synConstant">6</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'N'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'O'</span>, <span class="synConstant">16</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'P'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'Q'</span>, <span class="synConstant">7</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'R'</span>, <span class="synConstant">14</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'S'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'T'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'U'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'V'</span>, <span class="synConstant">5</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'W'</span>, <span class="synConstant">13</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'X'</span>, <span class="synConstant">3</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'Y'</span>, <span class="synConstant">2</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'Z'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'['</span>, <span class="synConstant">11</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'\\'</span>, <span class="synConstant">14</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">']'</span>, <span class="synConstant">13</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'^'</span>, <span class="synConstant">10</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'_'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'`'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'a'</span>, <span class="synConstant">20</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'b'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'c'</span>, <span class="synConstant">26</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'d'</span>, <span class="synConstant">30</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'e'</span>, <span class="synConstant">33</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'f'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'g'</span>, <span class="synConstant">6</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'h'</span>, <span class="synConstant">31</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'i'</span>, <span class="synConstant">21</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'j'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'k'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'l'</span>, <span class="synConstant">26</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'m'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'n'</span>, <span class="synConstant">19</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'o'</span>, <span class="synConstant">33</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'p'</span>, <span class="synConstant">26</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'q'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'r'</span>, <span class="synConstant">37</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'s'</span>, <span class="synConstant">23</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'t'</span>, <span class="synConstant">28</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'u'</span>, <span class="synConstant">17</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'v'</span>, <span class="synConstant">8</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'w'</span>, <span class="synConstant">22</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'x'</span>, <span class="synConstant">9</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'y'</span>, <span class="synConstant">12</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'z'</span>, <span class="synConstant">4</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'{'</span>, <span class="synConstant">10</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'|'</span>, <span class="synConstant">7</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'}'</span>, <span class="synConstant">12</span><span class="synStatement">);</span> <span class="synStatement">(</span><span class="synConstant">'~'</span>, <span class="synConstant">9</span><span class="synStatement">)]</span> //<span class="synStatement">let</span> myCode <span class="synStatement">=</span> <span class="synConstant">&quot;System.Console.Write(\&quot;hello, world\&quot;)&quot;</span> <span class="synStatement">let</span> myCode <span class="synStatement">=</span> <span class="synConstant">&quot;printf&lt;|\&quot;%s\&quot;&lt;|\&quot;hello,\\u0020world\&quot;&quot;</span> <span class="synStatement">let</span> myCount <span class="synStatement">=</span> myCode <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.distinct <span class="synStatement">|&gt;</span> <span class="synPreProc">Seq</span>.countBy id <span class="synStatement">let</span> count <span class="synStatement">=</span> addCount othersCount myCount printfn <span class="synConstant">&quot;%s&quot;</span> myCode printfn <span class="synConstant">&quot;%d&quot;</span> <span class="synStatement">(</span>calc count myCode<span class="synStatement">)</span> <span class="synConstant">0</span> </pre> <p>実行結果は、20,964点。もしかしたら50位以内には入れたかもしれないけど、他の人のスコアも変動するので、実際はどうでしょうね。(計算すれば出ると思いますが、面倒なのでコードに落としていません)</p> matarillo 猫かわいい hatenablog://entry/26006613532097945 2015-05-23T09:58:02+09:00 2020-03-09T04:53:04+09:00 http://www.meetup.com/FunctionalKats/ <p><a href="http://www.meetup.com/FunctionalKats/" class="http-image"><img src="http://photos1.meetupstatic.com/photos/theme_head/e/8/d/d/full_6779613.jpeg" class="http-image" alt="http://www.meetup.com/FunctionalKats/"></a> <a href="http://www.meetup.com/FunctionalKats/">http://www.meetup.com/FunctionalKats/</a></p> matarillo kenokabeさん hatenablog://entry/26006613532097941 2015-04-30T23:30:15+09:00 2020-03-09T04:53:03+09:00 kenokabeさんは、自説の組み立て方、参照する先行研究や書籍が普通ではないので突っ込まれやすいにも拘わらず自説が正しいという態度を崩さない、知人だったらわりと面倒なお方だなという印象なんだけど、ここに書いてたことにはそんなに違和感ないな。 http://kenokabe-techwriting.blogspot.jp/2015/04/amazon102-93.html むしろ書評を書いた人が、ラムダ式とクロージャを混同してるんじゃないのか。 <p>kenokabeさんは、自説の組み立て方、参照する先行研究や書籍が普通ではないので突っ込まれやすいにも拘わらず自説が正しいという態度を崩さない、知人だったらわりと面倒なお方だなという印象なんだけど、ここに書いてたことにはそんなに違和感ないな。</p> <p><a href="http://kenokabe-techwriting.blogspot.jp/2015/04/amazon102-93.html">http://kenokabe-techwriting.blogspot.jp/2015/04/amazon102-93.html</a></p> <p>むしろ書評を書いた人が、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%E0%A5%C0%BC%B0">ラムダ式</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A1%BC%A5%B8%A5%E3">クロージャ</a>を混同してるんじゃないのか。</p> matarillo モナド構文糖 hatenablog://entry/26006613532097937 2015-03-31T06:14:56+09:00 2020-03-09T04:53:02+09:00 モナドが便利で、モナド構文糖が便利だってことには特に異論がないんだけど、 それならそれでHaskellのdo-returnみたいに逐次実行に似せるほうが絶対にいいと思う。 そうでなければ、もっとこう、bindとかunitとかそういう語彙を前面に出してほしい。 つまり、Scalaのように、for-yieldとかflatMapというリスト中心の語彙でモナドを扱うのは、どう考えてもキモイ。 (LINQのfrom-selectとかSelectManyとかのあれでモナドを扱うのは、さらにキモイ) という感覚は、Scalaユーザーと共有することはできないだろうなあ…… (2016/7追記) scala 界… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>が便利で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>構文糖が便利だってことには特に異論がないんだけど、 それならそれで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>のdo-returnみたいに逐次実行に似せるほうが絶対にいいと思う。 そうでなければ、もっとこう、bindとかunitとかそういう語彙を前面に出してほしい。</p> <p>つまり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>のように、for-yieldとかflatMapというリスト中心の語彙で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>を扱うのは、どう考えてもキモイ。 (<a class="keyword" href="http://d.hatena.ne.jp/keyword/LINQ">LINQ</a>のfrom-selectとかSelectManyとかのあれで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>を扱うのは、さらにキモイ)</p> <p>という感覚は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>ユーザーと共有することはできないだろうなあ……</p> <p>(2016/7追記)</p> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/scala">scala</a> 界隈でも for はちょっと…という意見はたまに見るし、F# の方が筋いいよねみたいな話 rpscala の懇親会でやった記憶ある。</p>&mdash; りりかるろじかる (@lyrical_logical) <a href="https://twitter.com/lyrical_logical/status/758498297682145280">2016年7月28日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いやまあ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>のforは最後がmapじゃないといけない縛りとかあって不便なので当然<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>のdoの方がいいに決まってますよ。 <a href="https://t.co/NAt2oVzi35">https://t.co/NAt2oVzi35</a></p>&mdash; 水島宏太(証明力強化月間) (@kmizu) <a href="https://twitter.com/kmizu/status/758512390602264576">2016年7月28日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">&quot;<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>構文糖 - 猫と<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>について書く代わりに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>とF#について書くmatarilloの日記 (<a href="http://blog.hatena.ne.jp/matarillo/">id:matarillo</a>(<a href="https://profile.hatena.ne.jp/matarillo/">https://profile.hatena.ne.jp/matarillo/</a>) / <a href="https://twitter.com/matarillo">@matarillo</a>) <a href="https://t.co/zmh9pxz7cr">https://t.co/zmh9pxz7cr</a>&quot; については、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>ユーザとは十分共有できる感覚だと思いますよ</p>&mdash; 水島宏太(証明力強化月間) (@kmizu) <a href="https://twitter.com/kmizu/status/758513589854449664">2016年7月28日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>lyrical_logicalさんのツイートを見て、お、追記しておこう、と思ったら、kmizuさんもツイートしてた。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>のfor式が不便(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>のdoとreturnみたいに独立してない)というのはそう思うんだけど、言いたかったのはそういうとこじゃないんですよね。</p> <p>どっちかというと</p> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/kmizu">@kmizu</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>とか知ってる人には、flatMapはbindだしfor式はdo式の不便なものという感じで説明できるし、そういうの知らない人向けには、コレクションをfor式でまず扱えて、それに加えてflatMap, mapを実装した任意の型に適用できるので</p>&mdash; 水島宏太(証明力強化月間) (@kmizu) <a href="https://twitter.com/kmizu/status/758685993528471554">2016年7月28日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/kmizu">@kmizu</a> implicit parameter≒型クラスということ、研究関係以外では最初は全然言ってなかったの(今はもう知られてるからそうでもないかもだけど)もそうだけど、小難しい(そうな)概念をそのままの語彙で導入していない点はOdersky先生のバランス感覚だと思ってる。</p>&mdash; 水島宏太(証明力強化月間) (@kmizu) <a href="https://twitter.com/kmizu/status/758687045988392960">2016年7月28日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>このあたりが感覚を共有できないと思うあたりで。「コレクションをfor式でまず扱えて」まではいいんだけど、そこから「それに加えてflatMap, mapを実装した任意の型に適用できる」には飛躍があるよね、とか、implicit parameterって結局型クラス以外で使わないんだったら他に名前なかったのか、とかなんですよね。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>(および設計者のOdersky先生)の選択なんで間違いだとかダメだとかイケてないとかDisりたいわけじゃなくて感覚の問題。</p> matarillo 遅延評価とfoldr/foldl hatenablog://entry/26006613532097932 2015-03-14T16:10:52+09:00 2020-03-09T04:53:02+09:00 Haskellの遅延評価のイメージは「まず式を立てる(サンクを作る)けど、値の評価はまた別の話」。 foldrは foldr f acc [x0, x1, x2, x3, ... , xn] = x0 `f` (foldr f acc [x1, x2, x3, ... , xn]) = x0 `f` (x1 `f` (x2 `f` (x3 `f` ... `f` (xn `f` acc) ... ))) こんな感じで、カッコの内側である右から計算するように見える式を立てるというイメージ。 が、評価は遅延評価なのでカッコの外側つまり左から評価するので、そのたびごとにリスト [x0, x1, ..… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>の遅延評価のイメージは「まず式を立てる(サンクを作る)けど、値の評価はまた別の話」。</p> <p><code>foldr</code>は</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink> foldr f acc [x0, x1, x2, x3, <span class="synStatement">...</span> , xn] <span class="synStatement">=</span> x0 <span class="synStatement">`f`</span> (foldr f acc [x1, x2, x3, <span class="synStatement">...</span> , xn]) <span class="synStatement">=</span> x0 <span class="synStatement">`f`</span> (x1 <span class="synStatement">`f`</span> (x2 <span class="synStatement">`f`</span> (x3 <span class="synStatement">`f`</span> <span class="synStatement">...</span> <span class="synStatement">`f`</span> (xn <span class="synStatement">`f`</span> acc) <span class="synStatement">...</span> ))) </pre> <p>こんな感じで、カッコの内側である右から計算するように見える式を立てるというイメージ。</p> <p>が、評価は遅延評価なのでカッコの外側つまり左から評価するので、そのたびごとにリスト [x0, x1, ... , xn] を1つづつバラしていくことが可能。よって途中で打ち切る場合なら無限リストでも問題にならない。</p> <p><code>foldl</code>は</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink> foldl f acc [x0, x1, x2, x3, <span class="synStatement">...</span> , xn] <span class="synStatement">=</span> foldl f (acc <span class="synStatement">`f`</span> x0) [x1, x2, x3, <span class="synStatement">...</span> , xn] <span class="synStatement">=</span> <span class="synStatement">...</span> ((((acc <span class="synStatement">`f`</span> x0) <span class="synStatement">`f`</span> x1) <span class="synStatement">`f`</span> x2) <span class="synStatement">`f`</span> x3) <span class="synStatement">`f`</span> <span class="synStatement">...</span> <span class="synStatement">`f`</span> xn </pre> <p>こんな感じで、カッコの内側である左から計算するように見える式を立てるいうイメージ。</p> <p>が、評価は遅延評価なのでカッコの外側つまり右から評価するので、リスト [x0, x1, ... , xn] は全部バラさないといけないから、無限リストだと計算が終わらなくなるし、有限リストでもメモリをたくさん必要とする(メモリについては<code>foldl'</code>を使うという手があるが)。</p> matarillo 貧者の型クラス hatenablog://entry/26006613532097926 2014-04-29T04:01:10+09:00 2020-03-09T04:53:01+09:00 去年、こんなのをメモしてた。 http://haskell.g.hatena.ne.jp/matarillo/20130524/1369369774 http://haskell.g.hatena.ne.jp/matarillo/20130527/1369636675 これってオダスキー先生のこれ↓がベースなのか! http://lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf (追記)というわけで、C#で書いてみた。 <p>去年、こんなのをメモしてた。</p> <ul> <li><a href="http://haskell.g.hatena.ne.jp/matarillo/20130524/1369369774">http://haskell.g.hatena.ne.jp/matarillo/20130524/1369369774</a></li> <li><a href="http://haskell.g.hatena.ne.jp/matarillo/20130527/1369636675">http://haskell.g.hatena.ne.jp/matarillo/20130527/1369636675</a></li> </ul> <p>これってオダスキー先生のこれ↓がベースなのか!</p> <p><a href="http://lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf">http://lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf</a></p> <p>(追記)というわけで、<a href="http://d.hatena.ne.jp/matarillo/20140429">C#で書いてみた</a>。</p> matarillo OKWaveの質問 hatenablog://entry/26006613532097921 2014-02-17T10:25:00+09:00 2020-03-09T04:53:00+09:00 Graham Hutton著「プログラミングHaskell」の第8章関数型パーサーを勉強しています。 本の中にあるソースコードではdo記法などが使えないため、動きません。 サポートページにプログラムがあります。そのプログラムの意味がよくわかりません。 教えていただけないでしょうか。 プログラミングHaskellでHaskellを学んだ私が来ましたよ。 OKWaveにアカウントを作るつもりはないですが。 まず、newtypeで新しい型を定義していると思うのですが、右辺のPというのがなにかわかりません。 また、instance Monad Parser whereやinstance MonadPl… <blockquote cite="http://okwave.jp/qa/q8468578.html" title="プログラミングHaskell 第8章関数型パーサー | その他(プログラミング)のQ&amp;A【OKWave】"> <p>Graham Hutton著「プログラミング<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>」の第8章関数型パーサーを勉強しています。 本の中にある<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>ではdo記法などが使えないため、動きません。 サポートページにプログラムがあります。そのプログラムの意味がよくわかりません。 教えていただけないでしょうか。<p> </blockquote> <p>プログラミング<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>を学んだ私が来ましたよ。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/OKWave">OKWave</a>にアカウントを作るつもりはないですが。</p> <blockquote> <p>まず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/newtype">newtype</a>で新しい型を定義していると思うのですが、右辺のPというのがなにかわかりません。<br /> また、instance <a class="keyword" href="http://d.hatena.ne.jp/keyword/Monad">Monad</a> Parser whereやinstance MonadPlus Parser whereの意味もわかりません。 その下で、return, >=, mzero, mplusといった関数を定義する意味もわかりません。 よろしくおねがいします。</p> </blockquote> <p>この本は、コードを写経して動かしながら学ぼうという向きにはつらくて、「第8章 関数型パーサー」の中に >>= とか return とか do記法とかが出てくるのだけど、そこには嘘があって、<strong>きちんと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>として定義された型でしかdo記法は使えない</strong>はずなのに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>として型を定義する話は第8章にはぜんぜん出てこない。</p> <p>第8章の頭には</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink><span class="synType">type</span> Parser a <span class="synStatement">=</span> String <span class="synStatement">-&gt;</span> [(a, String)] </pre> <p>って書いてあるけど、<strong>これではdo記法は使えない</strong>のだ。</p> <p>じゃあどう定義すればParser型でdo記法が使えるのか、というと、それがダウンロードできるサンプルコードでの定義のやり方なのだけど、この方法は第8章まで読んだだけでは理解できない。なぜなら、型クラスの話は「10.6 クラスと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>の宣言」まで出てこないからだ。</p> <p>その代わり、第10章まで読めば、</p> <blockquote> <p>instance <a class="keyword" href="http://d.hatena.ne.jp/keyword/Monad">Monad</a> Parser whereやinstance MonadPlus Parser whereの意味</p> </blockquote> <p>とか、</p> <blockquote> <p>その下で、return, >=, mzero, mplusといった関数を定義する意味</p> </blockquote> <p>については理解できると思う。</p> <p>とはいえ、</p> <p><strong>この本にはMonadPlusの説明なんか1行もでてこないけどな!</strong></p> <p>しかもしかも、サンプルコードには</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink><span class="synType">newtype</span> Parser a <span class="synStatement">=</span> P (String <span class="synStatement">-&gt;</span> [(a,String)]) </pre> <p>って書いてあるけど、</p> <p><strong>この本には<a class="keyword" href="http://d.hatena.ne.jp/keyword/newtype">newtype</a>キーワードの説明なんか1行もでてこないけどな!</strong></p> <p>というわけで、質問者のあなたがわからないのも当然ですわ。この本以外を使って自学するしかないです。</p> <p>それではあんまりなので、少しだけ説明しましょうか。</p> <dl> <dt>MonadPlus</dt><dd>モノイドの性質をあわせ持つ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>を表す型クラス。ざっくりいうと、足し算ができる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%CA%A5%C9">モナド</a>。この本のParser型では、パーサー同士を連結できるという意味。</dd> <dt><a class="keyword" href="http://d.hatena.ne.jp/keyword/newtype">newtype</a>キーワード</dt><dd>dataキーワードに似た、新しい型を定義する文法。Pは値コンスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>タ。dataキーワードとの違いは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/newtype">newtype</a>で定義された値コンスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>タは正格なこと。パターンマッチの動きも違ってくる。</dd> </dl> <p>とはいえ、ぶっちゃけこのあたりのことは、この本を読み進める上ではわからなくてもいいです。</p> matarillo F#の立ち位置 hatenablog://entry/26006613532097918 2013-11-22T14:43:33+09:00 2020-03-09T04:53:00+09:00 いげ太さんがときどきぼやいてたかと思いますが(追記: 不正確でした。いげ太さんからのコメントは下に)、「F#はなーんかMSに冷遇されてねえ?そのせいか、C#からF#に乗り換える人も少なくね?」みたいな話があります。 それは正しいといえば正しいのですが、コインの裏表のようにも思われて。 C#は、いろんな機能を貪欲にぶっこんできているわけじゃないですか。LINQみたいな関数型プログラミング由来の機能とか。asyncとか。 で、そのぶっこみかたというのが、割とコンパイラががんばるタイプの、キーワードが増えていくやつじゃないですか。 そんで、その様を「専用の構文をどんどん追加していくと、その言語にはど… <p><del datetime="2013-11-24T22:55:35+09:00">いげ太さんがときどきぼやいてたかと思いますが</del>(追記: 不正確でした。いげ太さんからのコメントは下に)、「F#はなーんかMSに冷遇されてねえ?そのせいか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>からF#に乗り換える人も少なくね?」みたいな話があります。 それは正しいといえば正しいのですが、コインの裏表のようにも思われて。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>は、いろんな機能を貪欲にぶっこんできているわけじゃないですか。<a class="keyword" href="http://d.hatena.ne.jp/keyword/LINQ">LINQ</a>みたいな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%D8%BF%F4%B7%BF%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">関数型プログラミング</a>由来の機能とか。asyncとか。</p> <p>で、そのぶっこみかたというのが、割と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ががんばるタイプの、キーワードが増えていくやつじゃないですか。</p> <p>そんで、その様を「<a href="http://bleis-tift.hatenablog.com/entry/asyncawaitdis">専用の構文をどんどん追加していくと、その言語にはどんどんゴミの山が積みあがっていきます。</a>」と厳しく指摘されたりするわけじゃないですか。</p> <p>で、なんで<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>はそういう(言わば、ダサい)方針なのかというと、言語仕様についてもユーザービリティテストを実施して、その結果がおれらみたいなボンクラにとって難しすぎるとわかると却下していたりするからなんだけど、その中に含まれる1要因として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>、というか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Studio">Visual Studio</a>で開発したり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>時にステップ実行したりするときにわかりやすいかどうか、というのもあるんじゃないかなと。</p> <p>イメージしてるのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>のテンプレート機能なんだけど、あれ、エラーメッセージが宇宙レベルでヤバイって話があるじゃないですか。そんな機能、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>には絶対入らないですよ。まああれは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時のエラーですが……</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>に新機能が入るときは、VSの方も更新しないといけないことが多くて。逆に、VSの方で対応できない(つまり、「わかりやすく」見せることができない)ような機能は却下されたり、違う形に変更されたりするわけで。</p> <p>F#の言語仕様はそこまでVSにべったりにならないのが、自由で良いところでもあり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>ユーザーが移行してこないという意味で悪いところでもあるという。</p> <p>あとはあれだ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/VB">VB</a>な。そういう<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>べったりの言語の面倒は2つで十分ですよ!という。(それがしんどくてかどうかはわからないが、Roslynはどちらの言語もカバーするようになっている)</p> <p>(追記)いげ太さんのツイート。</p> <p><a href="https://twitter.com/igeta/status/404427081200578560">https://twitter.com/igeta/status/404427081200578560</a></p> <p><a href="https://twitter.com/igeta/status/404427405898432513">https://twitter.com/igeta/status/404427405898432513</a></p> matarillo 関数適用と関数合成 hatenablog://entry/26006613532097908 2013-06-21T02:06:28+09:00 2020-03-09T05:01:52+09:00 では、こんな関数があったとき replicate 2 (product (map (*3) (zipWith max [1,2] [4,5]))) 関数合成をして、まっとうな記述をするとこう書けるらしい。 replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5] Haskell学びたてのころは、どういう発想するとこうなるのか(そしてこの書き方の何が嬉しいのか)あまりわかってなかった。 F#を学んだことによって、 (replicate 2 << product << map (*3)) <| (zipWith max [1,2] [4,… <blockquote><p>では、こんな関数があったとき</p> <p><code> replicate 2 (product (map (*3) (zipWith max [1,2] [4,5]))) </code></p> <p>関数合成をして、まっとうな記述をするとこう書けるらしい。</p> <p><code> replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5] </code></p></blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Haskell">Haskell</a>学びたてのころは、どういう発想するとこうなるのか(そしてこの書き方の何が嬉しいのか)あまりわかってなかった。</p> <p>F#を学んだことによって、</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink> (replicate <span class="synConstant">2</span> <span class="synStatement">&lt;&lt;</span> product <span class="synStatement">&lt;&lt;</span> map (<span class="synStatement">*</span><span class="synConstant">3</span>)) <span class="synStatement">&lt;|</span> (zipWith max [<span class="synConstant">1</span>,<span class="synConstant">2</span>] [<span class="synConstant">4</span>,<span class="synConstant">5</span>]) </pre> <p>という目で見ることができるようになった。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の記号が違うだけでだいぶ雰囲気が変わるもんだ。</p> <p>でもやっぱりF#みたいに左から書き、左から読みたいな。</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink>(zipWith max [<span class="synConstant">1</span>,<span class="synConstant">2</span>] [<span class="synConstant">4</span>,<span class="synConstant">5</span>]) <span class="synStatement">|&gt;</span> (map (<span class="synStatement">*</span><span class="synConstant">3</span>) <span class="synStatement">&gt;&gt;</span> product <span class="synStatement">&gt;&gt;</span> replicate <span class="synConstant">2</span>) </pre> <p>んで合成関数を再利用しないんだったらもういっそ</p> <pre class="code lang-haskell" data-lang="haskell" data-unlink>zipWith max [<span class="synConstant">1</span>,<span class="synConstant">2</span>] [<span class="synConstant">4</span>,<span class="synConstant">5</span>]) <span class="synStatement">|&gt;</span> map (<span class="synStatement">*</span><span class="synConstant">3</span>) <span class="synStatement">|&gt;</span> product <span class="synStatement">|&gt;</span> replicate <span class="synConstant">2</span> </pre> matarillo 前回の記事 hatenablog://entry/26006613532097896 2013-05-27T06:37:55+09:00 2020-03-09T04:52:58+09:00 個々の型に適合する関数群の実装をレコードのいちインスタンスとして渡してるわけね。サンプルでは、intならint、floatならfloat用の実装を用意している。これって目的は果たすのかな? <p>個々の型に適合する関数群の実装をレコードのいち<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>として渡してるわけね。サンプルでは、intならint、floatならfloat用の実装を用意している。これって目的は果たすのかな?</p> matarillo ジェネリックレコード型 hatenablog://entry/26006613532097901 2013-05-27T06:29:49+09:00 2020-03-09T04:52:58+09:00 前回の記事のど頭のこれ type 'a Num = { ... } はジェネリックレコード型の定義のようだ。'a listとか'a optionみたいに'a Numを定義している。 ところで、Num<'a>と書くのと同じなんだろうけど、そう書かない理由は何だろう。何か使い分けでもあるのかな。 <p><a href="http://haskell.g.hatena.ne.jp/matarillo/20130524/1369369774">前回の記事</a>のど頭のこれ</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> 'a <span class="synConstant">Num</span> <span class="synStatement">=</span> <span class="synStatement">{</span> ... <span class="synStatement">}</span> </pre> <p>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A5%A7%A5%CD%A5%EA%A5%C3%A5%AF">ジェネリック</a>レコード型の定義のようだ。<code>'a list</code>とか<code>'a option</code>みたいに<code>'a Num</code>を定義している。 ところで、<code>Num&lt;'a&gt;</code>と書くのと同じなんだろうけど、そう書かない理由は何だろう。何か使い分けでもあるのかな。</p> matarillo Poor Mans' Type Classes hatenablog://entry/26006613532097890 2013-05-24T04:29:34+09:00 2020-03-09T04:52:57+09:00 .NETのCLRに高階ジェネリクス(型クラス、高カインド)を!という要望はMSから断られているわけだけども。 回答にある「Steffenがコメント欄に書いたようなやり方でエンコードできるよ」というのが気になった。 時間を見つけてこのコードを勉強してやろう。 (おまけ) https://code.google.com/p/fsharp-typeclasses/ http://ntypeclasses.codeplex.com/ <p><a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2228766-add-higher-order-generics-to-f-type-classes-">.NETのCLRに高階ジェネリクス(型クラス、高カインド)を!という要望はMSから断られているわけだけども</a>。</p> <p>回答にある「Steffenがコメント欄に書いたようなやり方で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C9">エンコード</a>できるよ」というのが気になった。</p> <script src="https://gist.github.com/forki/1400378.js"></script> <p>時間を見つけてこのコードを勉強してやろう。</p> <p>(おまけ) <a href="https://code.google.com/p/fsharp-typeclasses/">https://code.google.com/p/fsharp-typeclasses/</a> <a href="http://ntypeclasses.codeplex.com/">http://ntypeclasses.codeplex.com/</a></p> matarillo Google Code Jam Japan 2011 予選問題B hatenablog://entry/26006613532097885 2013-05-14T18:35:07+09:00 2020-03-09T04:52:57+09:00 日にちを逆から計算するというのは早めに気づいたのだけど、Largeを解けるようにするのにえらく時間がかかった。 ループをk回ずつまわさないようにするために、消費期限が長いものから順に何杯ずつ飲むのかを計算して掛け算する方針。 <p>日にちを逆から計算するというのは早めに気づいたのだけど、Largeを解けるようにするのにえらく時間がかかった。</p> <p>ループをk回ずつまわさないようにするために、消費期限が長いものから順に何杯ずつ飲むのかを計算して掛け算する方針。</p> <script src="https://gist.github.com/matarillo/5578222.js"></script> matarillo Haskellのポイントフリー hatenablog://entry/26006613532097881 2013-04-26T02:36:01+09:00 2020-03-09T04:52:56+09:00 読みにくいからやめてほしい。 自己満足以外に実用的な意味があるのかどうか。 そもそも、セクションとかflipとかを使いまくらないと実現できないわけでしょう? unlambdaやlazy kは実用言語じゃないでしょう? <p>読みにくいからやめてほしい。 自己満足以外に実用的な意味があるのかどうか。 そもそも、セクションとかflipとかを使いまくらないと実現できないわけでしょう? unlambdaやlazy kは実用言語じゃないでしょう?</p> matarillo ビットボンバーマン(第8回オフラインリアルタイムどう書くの問題) hatenablog://entry/26006613532097873 2013-04-23T22:57:47+09:00 2020-03-09T04:52:55+09:00 http://qiita.com/items/709d61dff282cff7a890 http://qiita.com/items/463311ff1ce4dd2cc943 <p><a href="http://qiita.com/items/709d61dff282cff7a890">http://qiita.com/items/709d61dff282cff7a890</a></p> <p><a href="http://qiita.com/items/463311ff1ce4dd2cc943">http://qiita.com/items/463311ff1ce4dd2cc943</a></p> matarillo バス代の計算(第9回オフラインリアルタイムどう書くの問題) hatenablog://entry/26006613532097877 2013-04-23T22:57:46+09:00 2020-03-09T04:52:56+09:00 http://qiita.com/items/84255ac417ef25069a3b http://qiita.com/items/7385db8cce051cb499d7 <p><a href="http://qiita.com/items/84255ac417ef25069a3b">http://qiita.com/items/84255ac417ef25069a3b</a></p> <p><a href="http://qiita.com/items/7385db8cce051cb499d7">http://qiita.com/items/7385db8cce051cb499d7</a></p> matarillo ポーカーの役判定(第10回オフラインリアルタイムどう書くの参考問題) hatenablog://entry/26006613532097868 2013-04-22T01:53:55+09:00 2020-03-09T04:52:54+09:00 haskellグループなのにF#のエントリ。大目に見てね。 F#の練習に http://qiita.com/items/d819d1e5f2378317511e の問題を解いてみた。 (横浜へなちょこプログラミング勉強会には参加したことないですが……横からすみません) http://qiita.com/items/80c2c22d3224cb7c448c 以下、頭の中をトレース出力。 型を用意 手は5枚のカードから構成され、カードはスート(絵柄マーク)とランク(番号)を持っている。 スートは列挙型でもいいんだけど、整数値を使うことはなさそうなので値を指定しない。こうするとSuit型は判別共用体… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/haskell">haskell</a>グループなのにF#のエントリ。大目に見てね。</p> <p>F#の練習に <a href="http://qiita.com/items/d819d1e5f2378317511e">http://qiita.com/items/d819d1e5f2378317511e</a> の問題を解いてみた。 (横浜へなちょこプログラミング勉強会には参加したことないですが……横からすみません)</p> <p><a href="http://qiita.com/items/80c2c22d3224cb7c448c">http://qiita.com/items/80c2c22d3224cb7c448c</a></p> <p>以下、頭の中をトレース出力。</p> <h2>型を用意</h2> <p>手は5枚のカードから構成され、カードはスート(絵柄マーク)とランク(番号)を持っている。</p> <p>スートは列挙型でもいいんだけど、整数値を使うことはなさそうなので値を指定しない。こうするとSuit型は判別共用体になるのかな。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Suit</span> <span class="synStatement">=</span> <span class="synConstant">Spade</span> <span class="synStatement">|</span> <span class="synConstant">Heart</span> <span class="synStatement">|</span> <span class="synConstant">Diamond</span> <span class="synStatement">|</span> <span class="synConstant">Club</span> </pre> <p>ランクを数値型や列挙型にするかどうかかなり悩んだが、今回はそうしなかった。なぜかというとAの存在。 Aって1にも14にもなるカードなのだが、そのロジックをどこに入れるかが悩ましい。 とりあえず Rank -> int list という変換関数があれば何とかなるかなと目星をつけ、こちらも判別共用体に。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Rank</span> <span class="synStatement">=</span> <span class="synConstant">R2</span> <span class="synStatement">|</span> <span class="synConstant">R3</span> <span class="synStatement">|</span> <span class="synConstant">R4</span> <span class="synStatement">|</span> <span class="synConstant">R5</span> <span class="synStatement">|</span> <span class="synConstant">R6</span> <span class="synStatement">|</span> <span class="synConstant">R7</span> <span class="synStatement">|</span> <span class="synConstant">R8</span> <span class="synStatement">|</span> <span class="synConstant">R9</span> <span class="synStatement">|</span> <span class="synConstant">R10</span> <span class="synStatement">|</span> <span class="synConstant">RJ</span> <span class="synStatement">|</span> <span class="synConstant">RQ</span> <span class="synStatement">|</span> <span class="synConstant">RK</span> <span class="synStatement">|</span> <span class="synConstant">RA</span> </pre> <p>カードはタプルの別名。 そして、さっきの変換関数はカードに対して定義することにした。 Aの特別扱いはここに反映される。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Card</span> <span class="synStatement">=</span> <span class="synConstant">Rank</span> <span class="synStatement">*</span> <span class="synConstant">Suit</span> <span class="synStatement">let</span> cardToNums <span class="synStatement">(</span>c:<span class="synConstant">Card</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">match</span> fst c <span class="synStatement">with</span> <span class="synStatement">|</span> <span class="synConstant">R2</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">2</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R3</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">3</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R4</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">4</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R5</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">5</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R6</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">6</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R7</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">7</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R8</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">8</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R9</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">9</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">R10</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">10</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">RJ</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">11</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">RQ</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">12</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">RK</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">13</span><span class="synStatement">]</span> <span class="synStatement">|</span> <span class="synConstant">RA</span> <span class="synStatement">-&gt;</span> <span class="synStatement">[</span><span class="synConstant">1</span><span class="synStatement">;</span><span class="synConstant">14</span><span class="synStatement">]</span> </pre> <p>手はカード5枚。リストにするかどうか迷った(ロジック上はリストの方が扱いやすい)が、5枚というのを明確にしたかったのでタプルにしてみた。 なんだか無駄なような気はするが。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">type</span> <span class="synConstant">Hand</span> <span class="synStatement">=</span> <span class="synConstant">Card</span> <span class="synStatement">*</span> <span class="synConstant">Card</span> <span class="synStatement">*</span> <span class="synConstant">Card</span> <span class="synStatement">*</span> <span class="synConstant">Card</span> <span class="synStatement">*</span> <span class="synConstant">Card</span> <span class="synStatement">let</span> toList <span class="synStatement">(</span>c0,c1,c2,c3,c4<span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">[</span>c0<span class="synStatement">;</span>c1<span class="synStatement">;</span>c2<span class="synStatement">;</span>c3<span class="synStatement">;</span>c4<span class="synStatement">]</span> </pre> <h2>役の判定ロジック</h2> <p>最初は、役をCategory型として判別共用体で定義した上で、Card -> Category list という判定関数を書こうかなと考えた。 次に、if文を並べて Card -> Category にしてもいいやと考え、実際に実装してみた。 しかし、最後に求められる出力は "RF" とか "-" といった文字列なので、Category -> string も必要になった。 なんだかば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>くなったので、Category型を排除して、 その代わりにアクティブパターンで役を判定し、文字列に変換するようにした。</p> <pre class="code lang-ocaml" data-lang="ocaml" data-unlink><span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">Flush</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">Straight</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">StraightFlush</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">RoyalFlush</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">FourFlush</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">FourStraight</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> <span class="synStatement">(|</span><span class="synConstant">FourStraightFlush</span><span class="synStatement">|_|)</span> : <span class="synConstant">Hand</span> <span class="synStatement">-&gt;</span> <span class="synType">unit</span> <span class="synType">option</span> <span class="synStatement">=</span> <span class="synStatement">????</span> <span class="synStatement">let</span> show <span class="synStatement">(</span>h:<span class="synConstant">Hand</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synStatement">match</span> h <span class="synStatement">with</span> <span class="synStatement">|</span> <span class="synConstant">RoyalFlush</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;RF&quot;</span> <span class="synStatement">|</span> <span class="synConstant">StraightFlush</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;SF&quot;</span> <span class="synStatement">|</span> <span class="synConstant">Flush</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;FL&quot;</span> <span class="synStatement">|</span> <span class="synConstant">Straight</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;ST&quot;</span> <span class="synStatement">|</span> <span class="synConstant">FourStraightFlush</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;4SF&quot;</span> <span class="synStatement">|</span> <span class="synConstant">FourFlush</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;4F&quot;</span> <span class="synStatement">|</span> <span class="synConstant">FourStraight</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;4S&quot;</span> <span class="synStatement">|</span> <span class="synStatement">_</span> <span class="synStatement">-&gt;</span> <span class="synConstant">&quot;-&quot;</span> </pre> <p>役の強さはこの show 関数に埋め込まれている(上から順に強い)。</p> <p>(書き途中)</p> matarillo