モナドは必要ないと思います。これらは、特定の種類の関数を操作しているときに自然に表示されるパターンにすぎません。私が今まで見たこの観点の最も良い説明は、ダン・ピポーニ(sigfpe)の優れたブログ投稿「あなたはモナドを発明したかもしれない!(そして多分あなたはすでに持っている)」であり、この答えはこの答えに触発されています。
あなたは州のモナドを使わずにゲームを書いたと言います。それはどのように見えましたか?次のようなタイプの関数を使用することになった可能性がありますopenChest :: Player -> Location -> (Item,Player)
(胸を開き、トラップでプレーヤーに損害を与え、見つかったアイテムを返す可能性があります)。これらを組み合わせる必要がある場合は、手動で行う(let (item,player') = openChest player loc ; (x,player'') = func2 player' y in ...
)か、状態モナドの>>=
演算子を再実装することができます。
または、ハッシュマップ/連想配列を使用する言語で作業していて、モナドを使用していないとします。いくつかの項目を調べて、それらを操作する必要があります。2人のユーザー間でメッセージを送信しようとしている可能性があります。
send username1 username2 = {
user1 = users[username1]
user2 = users[username2]
sendMessage user1 user2 messageBody
}
しかし、待ってください、これは機能しません。欠落している可能性がありusername1
ます。その場合、目的の値ではなく、または何かになります。または、連想配列でキーを検索すると、型の値が返されるため、これは型エラーになることもあります。代わりに、次のようなものを書く必要がありますusername2
nil
-1
Maybe a
send username1 username2 = {
user1 = users[username1]
if (user1 == nil) return
user2 = users[username2]
if (user2 == nil) return
sendMessage user1 user2 messageBody
}
または、を使用してMaybe
、
send username1 username2 =
case users[username1] of
Just user1 -> case users[username2] of
Just user2 -> Just $ sendMessage user1 user2 messageBody
Nothing -> Nothing
Nothing -> Nothing
いや!これは厄介で、過度にネストされています。そこで、失敗する可能性のあるアクションを組み合わせたある種の関数を定義します。多分何かのような
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
f >>= Just x = f x
f >>= Nothing = Nothing
だからあなたは書くことができます
send username1 username2 =
users[username1] >>= $ \user1 ->
users[username2] >>= $ \user2 ->
Just (sendMessage user1 user2 messageBody)
本当に使いたくない場合はMaybe
、実装することができます
f >>= x = if x == nil then nil else f x
同じ原則が適用されます。
しかし、実際には、「モナドを発明できたかもしれない」を読むことをお勧めします。 それは私がモナドについてこの直感を得た場所であり、それをより良くそしてより詳細に説明します。モナドは、特定のタイプで作業するときに自然に発生します。その構造を明示的にすることもあれば、そうでないこともありますが、それを控えているからといって、そこにないというわけではありません。その特定の構造で作業する必要がないという意味でモナドを使用する必要はありませんが、多くの場合、それは自然なことです。そして、ここでは他の多くのものと同様に、一般的なパターンを認識することで、いくつかのうまく一般的なコードを書くことができます。
Maybe
(また、私が使用した2番目の例が示すように、魔法の値に置き換えて、お風呂の水で赤ちゃんを捨てたことに注意してください。モナドであるからMaybe
といって、モナドのように使用する必要があるわけではありません。リストもモナドです。 、(形式のr ->
)関数もそうですが、それらを取り除くことを提案することはありません!:-))