読者です 読者をやめる 読者になる 読者になる

みどりねこ日記

よくわからないけど、頑張りますよ。

Haskellのモナド2(5)

Stateモナドはコンテナという見方より、計算と見たほうがいいと思います。Stateモナドは「内部の値に依存したり、書き換えたりする計算」を表しています。例えば、3体問題(互いに相互作用する3体以上からなる系を扱う問題)のモデリングをしているとしま…

Haskellのモナド2(4)

Haskellのリスト内包表記と、リストモナドの形が似ているのは興味深いですね。例えば、下のコードは三平方の定理を満たすものをリストアップする関数です。 pythags = [(x, y, z) | z <- [1..], x <- [1..z], y <- [x..z], x^2 + y^2 == z^2] これをリストモ…

Haskellのモナド2(3)

リストモナドの計算(型[a]で終わるもの)は「0個以上の値が結果となる計算」を表しています。例えば、三目並べをモデリングしているとします。ちょっとだけわざとらしいのですが、ここではゲームが進行する可能性のある状態を見つけることを問題とします。…

Haskellのモナド2(2)

Maybeモナドの計算(Maybeモナドで包まれたものが結果となる関数呼び出し)は、「失敗するかもしれない計算」を表現しています。これの良い例として、データベースのルックアップテーブルから条件にマッチするものを引っ張ってくる処理があります。ルックア…

Haskellのモナド2(1)

前回まではモナドをコンテナの表現方法として扱って来ました。すなわち、モナドを構造的に見てきたということです。しかし「なぜ」モナドを使うのかは完全には説明していません。なんといっても、モナドの構造はとてつもなくシンプルですので、そもそもなぜ…

Haskellのdo記法(4)

do記法の最後の式はdoブロックの結果となります。今までの例では、結果の型はIO ()、つまりIOモナドの空の値でした。前回の例を、受け取った名前を結果として返す関数、つまり型としてはIO Stringである関数として書き換えます。することといえば、最後にret…

Haskellのdo記法(3)

ユーザに氏名を尋ねるプログラムを考えましょう。 nameDo :: IO () nameDo = do putStr "What is your first name? " first <- getLine putStr "And your last name? " last <- getLine let full = first ++ " " ++ last putStrLn ("Pleased to meet you, " …

Haskellのdo記法(2)

do記法に変換するとき、下流に値を渡していく(>>=)演算子は何も渡さない(>>)演算子に比べてちょっとだけ難しいです。これらの値は do result <- action another_result <- another_action (action_based_on_previous_results result another_result) これを…

Haskellのdo記法(1)

do記法はモナディックなコードを書くための別の記法です。特にIOモナドのような、仕様として純粋な値を取り出すことが出来ないモナドを使った処理を書くのには便利です。対照的にMaybeやリストのようなモナドからは純粋な値をパターンマッチやそのための関数…

Haskellのモナド(11)

モナドは数学の分野の一つである圏論から来ました。嬉しいことに、Haskellでモナドを理解して利用するために、圏論を理解する必要は全くありません。しかし、圏論でのモナドの定義はHaskellのそれと少し違います。Haskellに持ってきた時に、圏論のそれと同じ…

Haskellのモナド(10)

結合性のおかげで、仮にネストしたとしても>>=演算子が計算の順番のみに対して影響することが保証されます。例えば、下のコードも等価であることが保証されています。 bothGrandfathers p = (father p >>= father) >>= (\gf -> (mother p >>= father) >>= (\…

Haskellのモナド(9)

returnの振る舞いは、右結合、左結合を満たすことという指定があります。また、returnは値をとるだけで、実際にはなんの計算もしない、と決まっています。例として、 maternalGrandfather p = do { m <- mother p; gm <- father m; return gm; } は以下のコ…

Haskellのモナド(8)

命令型言語のようにブロックを組み立てたいとしても、>>=やreturnにむちゃくちゃな機能をつけるわけにはいきません。以下の3つに従う必要があります。 m >>= return = m return x >>= f = f x (m >>= f) >>= g = m >>= (¥x -> f x >>= g) これがモナド則と…

Haskellのモナド(7)

前回までの説明で、おそらく>>=演算子とreturnが、Maybeを使ったコードを書くときに、煩雑なコードから解放されるために有益であると同意してもらえると思います。これがどうして動くのか、そしてこれが何を意味しているのかを考えましょう。その説明のため…

Haskellのモナド(6)

Functorは関数fmapを適用できる型です。fmapは、リストでいうmapと同じようなものです。圏論によると、すべてのモナドは定義上Functorでもあります。しかし、GHC(事実上のHaskell標準処理系)はそれらを別として捉えており、MonadクラスはFunctorクラスとな…

Haskellのモナド(5)

Haskellでは、型クラスであるモナドはモナドを表すものとして使われています。モナドはControl.MonadモジュールとPreludeの中で定義されています。 class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b fa…

Haskellのモナド(4)

Maybeモナドにおける>>=演算子の便利さを知るために、以下の2つの関数を提供する家系のデータベースがあるとします。 father :: Person -> Maybe Person mother :: Person -> Maybe Person これらは、誰かの父親・母親の名前を返すか、データベース中に存在…

Haskellのモナド(3)

モナドは以下の3つがあるものとして定義されています。 アクションの型をその結果の型から生成する方法。型コンストラクタMとされる場合が多い。 値を生成するだけのアクションを生成する方法。returnと呼ばれることが多い。 return :: a -> M a 型情報から…

Haskellのモナド(2)

モナドはHaskellにおいて非常に使い勝手のいい概念ですが、Haskell初心者には少々難しい概念でもあります。モナドには多くの機能があり、それ故、様々な人が別々の視点からモナドを説明するのでそれがモナドの汎用性に対する理解の混乱のもととなるのでしょ…

Haskellのモナド(1)

Haskellのモナドについて調べてたら、wikibooksの方に良さ気な解説が載ってましたので翻訳してみました。 「最初に、これをして、次にあれをして、そのあとに他のことをして。」というような論理的な順序が存在するプログラミングをしているときに、モナドは…