トップ «前の日記(2009-10-17) 最新 次の日記(2009-10-24)» 編集

Route 477



2009-10-19

[haskell] モナドって結局なんなの

社内勉強会でモナドについて発表しました。分かった気がするたびにすぐに手からすりぬけてしまう、それがモナド…!

追記:

モナドそのものが何なのかとか考えないほうがいいんじゃないですかね!

[Twitter / いーぐるとまとより引用]

まさにその通りだと思います(笑)。IOの使い方、Maybeの使い方、Stateの使い方などを押さえておけば、 中がどうなってるかなんて知らなくても大丈夫。

でも、モナドの持つ「なんか秘技がありそうな感じ」が、中を覗いてみたくさせるんですよね。 この、どこまで掘っても自分の知らないことが出てくる感じがHaskellの魅力なのかも。

Haskell の本当にすごいところは、「なぜなに」を問いかけることでいつまでもプログラマが成長できるところにある。

[ふぁぼったー / ikegami__より引用]

一問一答

Q. モナドって結局なんなんですか?

A. 関数型言語のための、一種のデザインパターンだと思えばいいかも。計算とその組み合わせ方を分離するという。

Q. 「モナド」っていう単語は具体的にどれのことを指すんでしょう?

A. 型コンストラクタ、>>=、returnの3つ組がモナドです。例えばIOモナド(IO, >>=, return)とか、Maybeモナド(Maybe, >>=, return)とか。

Q. >>=とreturnを定義するとどんな良いことがあるの?

A. 「do記法」という文法が使えます。

 do putStr "foo"
    putStr "bar"

 (putStr "foo") >>= (\_ -> putStr "bar")

のシンタックスシュガーなんですけど、上の方が読みやすいでしょ。

このように、do記法を使うと、純粋関数型言語のHaskellでも「手続き型っぽい雰囲気」を醸し出すことができます。 内部では>>=とreturnに展開されるので、結局関数呼び出しなんですけどね。

Q. モナドはどういう用途に使われてるの?

A. いろいろです。「関数のみで副作用をエミュレートする」のが多いのかな(Stateモナドなど)。他には、「途中で失敗するかもしれない計算をつなげる」(Maybeモナド)とか、「選択肢を全部ためした結果を生成する」(Listモナド)とかがあります。

Q. えっと…、いろいろできるのは分かったけど、どういう共通点があるんでしょうか?

A. だから>>=とreturnですって*1

 do x <- func1
    y <- func2
    return y

は、

 func1 >>= (\x -> func2 >>= (\y -> return y))

のように展開されます。雰囲気的には、func1の実行結果をxとし、func2を実行して、その結果であるyを返す…みたいに読めますよね。でも、 実際に何が起こるかはモナドの種類次第(>>=とreturnの定義次第)です。

Maybeモナドならば、func1がNothingを返したら、func2は実行されません。

Listモナドならば、リストxとリストyの要素の全ての組み合わせに対して、return yが評価されます。

まとめ

関数型言語のプログラムは、ネストした関数呼び出しをよく使います。

 f( g( h( i() ) ) )

この、関数呼び出しと関数呼び出しの「間」に仕掛けを組み込むのがモナドです。

…という理解でどうでしょうか先生!

一応、発表に使ったスライドを置いておきます。

リンク

感想

  • モナドの仕組みを知らなくても、do記法だけ知ってればHaskellのコードは書けます(多分)
  • というか仕組みを知ろうとすると、すげートリッキーな感じで理解するのが大変…
  • モナドを極めるとどんなことが出来るようになるんでしょうね?
  • Haskell使ってないのにモナドについて語ろうとするのがそもそも間違ってるね→そこでHaskell本ですよ

以下アフィリエイト。

4797336021

これ一冊でHaskellはだいたい分かります。(って品切れじゃん)

4873114233

Real World Haskell の日本語版。エラー処理からGUI、ネットワークに、最近流行り?のSTMと、 まさにReal Worldな感じの目次ですね。

あと、0521692695の訳書が11月初旬に出るそうです。 4839919623 と合わせて、4冊目のHaskell本ですね(和書として)。

*1 共通点(モナドの本質)が結局よくわかんなかったので逆ギレ

[ruby] gemcutterの使い方まとめ (2009年秋)

Rubyの素敵さのうちの何割かは、ライブラリを簡単に入れられるRubyGemsが占めていると思うyharaですこんばんわ。

で、そんなgemを公開するためのサイトとしてはRubyForgeが最も有名だったのですが、 最近、より簡単にgemを公開できるgemcutter.orgというサイトが普及しつつあります。

どれくらい簡単かというと、RubyForgeではWebフォームからアップロードしたり、あるいはRakefileを書いたりなどいろいろ必要なのに対し、gemcutterの場合は

 $ gem push mylibrary-1.2.3.gem

これだけです。お手軽ですね!

そんな手軽なgemcutterなので、「最新版はgemcutterに置いたよ」というライブラリがこれから増えていくものと思われます。 ここではgemcutter.orgからgemをインストールする方法を解説します。

(1) RubyGems 1.3.5以降が入ってることを確認する

$ gem --version

を実行して、1.3.5と表示されればOKです。

より古いバージョン(1.3.x)だった場合は、

$ gem update --system

で1.3.5に上がります。

もっと古いバージョン(1.1.xや1.2.x)だった場合は、

$ gem install rubygems-update
$ update_rubygems

としてください。

そもそもRubyGemsが入ってなかった人は、aptitude install rubygemsなど、環境に合わせてインストールしてください。 (パッケージマネージャが利用できない場合は、ここからzipをダウンロードし、

$ ruby setup.rb

としてください。)

(2) gemcutterをインストールする

RubyGems 1.3.5が用意できれば、あとは

$ gem install gemcutter

とするだけです。その後、gem tumbleを実行して、gemcutter.orgをgemの探索先に追加してください。*1

$ gem tumble
Thanks for using Gemcutter!
Your gem sources are now:
- http://gemcutter.org        # ←これが増えた
- http://gems.rubyforge.org

(3) gemcutterからgemをインストールする

gemcutter.orgでは既にたくさんのgemが公開されていますが、それらのインストールは今まで通り gem install foo とすればOKです。

(4) gemcutterでgemを公開する

ついでなのでgemの公開方法についても解説しておきます。

といっても、gemファイルさえできればあとは

$ gem push mylibrary-0.0.1.gem

とするだけなので、問題はどうやってgemファイルを作るかですね。

もしgitをお使いならば、jewelerを使うのが便利です。

gitが使えないならば…newgemを使うという方法があります。 gem install newgem → newgem foo → RakefileのFIXMEやTODOを編集 → rake gem でgemファイルができます。 この場合、gemファイルに含めるファイルをManifest.txtに書かなければいけないことに注意してください *2

あるいは、mylibrary.gemspecを手書きして、gem build mylibrary.gemspec する…という手もあります。 gemspecファイルの書き方は、るりまを見るか、 githubから適当なプロジェクトのgemspecファイルを参考にすれば良いでしょう。

*1 もう一度gem tumbleすると元に戻ります。

*2 jewelerの場合、gitリポジトリに登録されているファイル=gemの内容物になるので、Manifest.txtなどを作る必要がない