Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a return = pure -- return と pure は同じ class Functor f => Applicative f where pure :: a -> f a class Functor f where fmap :: (a -> b) -> (f a -> f b) (>>=) ── bind return / pure fmap ⽂脈つきの値 m aの中⾝を取り出し、第 ⼆引数の関数に渡す 値aに m の⽂脈を付与して返す 関数 a -> bを f a -> f bに変換する
プログラミングでの対応 (Haskell) 左単位律 pure で包んで bind ≡ 直接適⽤ ⾃⼰関⼿ T : C → C 対象関数: 型コンストラクタ m // m -> m aに写す pure a >>= f == f a 射関数: fmap :: (a -> b) -> (f a -> f b) 右単位律 pure で包み直しても元のまま ⾃然変換 η : Id ⇒ T 射関数: pure :: a -> m a ⾃然変換 μ : T² ⇒ T 射関数: join :: m (m a) -> m a (join x = x >>= id として bind から定義可能) m >>= pure == m 結合律 bind の結合順序を変えても結果は同じ (m >>= g) >>= h == m >>= (\x -> g x >>= h)
a findUser :: Int -> Maybe String findUser 1 = Just "Alice" findUser 2 = Just "Bob" findUser _ = Nothing Just u 値が取れた場合の処理 → main = case (findUser 1) of Just user -> print user Nothing -> print "No User" 同じ仲間: IO Either State List Nothing 失敗した場合の処理を書く 戻り値の型が Maybe aなので、呼び出し側は失敗可能性 という⽂脈を知ることができる ── どれも「⽂脈‧計算効果の付与」で共通
-> Maybe User findCompany :: User -> Maybe Company findAddress :: Company -> Maybe Address findUser :: Int -> Maybe User findCompany :: User -> Maybe Company findAddress :: Company -> Maybe Address do findUser 1 >>= \user -> findCompany user >>= \company -> findAddress company >>= \address -> return address user <- findUser 1 company <- findCompany user address <- findAdress company return address = 同じ意味 <- は各関数が返した⽂脈(Maybe etc…)の中の値を束縛する。前の結果が取れたら次へという合成の流れを⼿続き的に書ける