LoginSignup
30
17

More than 5 years have passed since last update.

なぜモナドが必要なのか?

Last updated at Posted at 2018-07-09

haskell - Why do we need monads? - Stack Overflow
の回答がわかりやすかったため翻訳させていただきました。


STEP 1

私たちは関数のみを使ってプログラミングしたい。(つまるところ「関数型プログラミング(FP)」)

STEP 2

その時、私たちは最初の大きな問題にぶつかる。

f(x) = 2 * x
g(x, y) = x / y

何が最初に実行されるべきだろうか?

どのように関数以外のものを使わずに、関数の羅列(プログラム)を作れるだろうか?

解決法

関数の合成。もしgを最初にして、次をfにしたいなら、f(g(x, y))と書く。この方法では、「プログラム」は次のような関数だ:

main = f(g(x, y))

良い感じだが…

STEP 3

次の問題: いくつかの関数は失敗する可能性を持っている(例えば、g(2, 0)は0除算となる)。

関数型プログラミングでは「例外」を持ってはいない(例外は関数ではない)。これをどのように扱うか?

解決法

関数に二種類のものを返すことができるようにする

g : Real,Real -> Real(二つの実数から一つの実数への関数)の代わりに、g : Real,Real -> Real | Nothing(二つの実数から一つの実数またはNothingへの関数)とする。

良さそうだ、しかし…

STEP 4

しかし、関数は一つの値のみ返すべきだ(シンプルにするため)。

解決法

戻り値のための新しい型を作ろう。
新しい型は、実数かNothingを閉じ込む「Box化型」だ。
そのため、g : Real,Real -> Maybe Realとなる。だがしかし…

STEP 5

現状、f(g(x, y))はどうなってしまうか?
fMaybe Realを引数として受け取る準備はできていない。
そして、Maybe Realを引数として受け取るために、gに接続(connect)する全ての関数を変更したくない。

解決法

関数を「connect」「compose」「link」するための、特別な関数を作ろう。
この方法は、舞台裏で、ある関数の出力(戻り値)を次の関数に渡すために合わせることができる。

私たちの場合は、g >>= f (gfへconnect/compose)となる。
私たちは>>=gの出力を拾い上げさせ、調査させ、Nothingの場合はfを呼び出すことなくNothingを返し、それ以外の場合はBox化された実数を取り出しfに与える。
(このアルゴリズムはMaybe型のための>>=の実装にすぎない)。

>>=は「Box化型」ごとに一度だけ書かれなければならないことに注意してほしい(Boxが異なれば、適用アルゴリズムは異なる)。

STEP 6

同じパターンを使って解決できるたくさんの問題がある。

  1. 「Box」を異なる意味/値を体系化/保存するために使う。そして、gのような「Box化された値」を返す関数を作る。
  2. composer/linkerであるg >>= fを、gの出力をfの入力に接続するために作る。このため、fを変える必要は全くない。

STEP 7

このテクニックで解決できる目立つ例として:

例1

関数の羅列(プログラム)内の全ての関数が共有することができる、グローバルな状態を持つ

解決法

StateMonad

例2

純粋でない関数が嫌いだ: 同じ入力に対して異なる出力を生成する関数。

解決法

これらの関数にマークをつけておいて、これらの関数にタグ付け/Box化された値を返させる。

IO Monad

幸せ!


ライセンス

StackOverflowのコンテンツはcc-by-saのライセンスの下でシェアすることができます。

以下に、翻訳元の情報を記します。

翻訳元のURL: https://stackoverflow.com/questions/28139259/why-do-we-need-monads

30
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
17