高校受験勉強

葉っぱ天国 > 勉強 > スレ一覧
2:真実に到達したレラクイル:2017/09/20(水) 02:06

Maybeモナド[編集]
オプション型 Maybe a を考えよう。これは型 a の値をひとつ持つか、全く持たないかのふたつの状態を表現する型である。これらを区別するために、二種類の代数的データ型構成子を持つ。Just tはひとつの値tを保持し、Nothingは値を何も保持しない。
data Maybe t = Just t | Nothing
この型を使って検査例外の簡単なものを作ってみたいとする。計算の途中で失敗した場合は、残りの計算は飛ばして結果Nothingを返し、すべての計算が成功した場合は何か値xを保持したJust xを返すことにする。
以下の例では、addはMaybe Int型のふたつの引数を受け取って、同じ型の結果を返す。mxとmyがともにJustである場合は、これらの値の和をJustに入れて返したい。もし、mxとmyのどちらかがNoneだった場合は、Nothingを返したい。こういった振る舞いをする関数を単純に実装しようとしたら、「if Nothing then Nothing else Just xのxに何かする」の形の場合わけを複数ネストすることになり、すぐやっかいなものになる[1]。
add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my =
case mx of
Nothing -> Nothing
Just x -> case my of
Nothing -> Nothing
Just y -> Just (x + y)
これを楽にするための、各計算を繋げる演算子を定義することができる。二項演算子 bind (>>=) は失敗する可能性のある計算の結果を、もうひとつの失敗する可能性のある計算へ連鎖する。最初の引数が Nothing だった場合は、二番目の引数(関数引数)は無視されて、単に計算全体が失敗する。もし、最初の引数が Just x だった場合は、この値 x は二番目の関数引数に渡されて、この関数の結果として新しい Maybe の値が返される。これは Just な値か失敗かのどちらかになる。
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing -- 失敗した計算は Nothing を返す
(Just x) >>= f = f x -- 値 x に関数 f を適用する
計算の状態に影響を与えずに値を投入する構築子は、Just がすでにそうなっている。
return :: a -> Maybe a
return x = Just x -- 値 x を包んで、型 (Maybe a) の値として返す
これらを使うことで、上の例は次のように書ける。
add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my = -- (Maybe Int) 型のふたつの値を足す関数。各入力は Nothing の場合がある
mx >>= (\x -> -- mx が Nothing でない場合に、値 x を抽出する
my >>= (\y -> -- my が Nothing でない場合に、値 y を抽出する
return (x + y))) -- 値(x+y)を包んで、(Maybe Int)型の値として和を返す
さらにdo記法という構文糖衣を使うことで、次のように書くことができる。
add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my = do
x <- mx
y <- my
return (x + y)
この種の操作は頻出なので、Haskellの標準関数(liftM2)が用意されている。これはふたつのモナド的な値(ここでは、ふたつのMaybe)と、その中身(ふたつの数値)を組み合わせる関数(加算)を受け取る関数であり、上の例は次のように書ける。
add :: Maybe Int -> Maybe Int -> Maybe Int
add = liftM2 (+)

俺から言えるのはこの程度。頑張れ。


全部 次100> キーワード
名前 メモ