Monad型クラス
>>=とreturnを実装した型
Monadのインスタンスにするためには、Applicativeのインスタンスである必要がある
ほんまは
しかしHaskellの歴史的に、最初にFunctorとMonadが導入され、その後にApplicativeが導入されたので、Haskell界の必ずしも全てのMonadがApplicativeというわけではない
が、適切に実装すれば全てのMonadがApplicativeになる
定義側と、使用側で見てみると良いかもmrsekut.icon
適当に命名してこのプロジェクト内で使用する
Monad型クラスの定義
code:hs
class Applicative m => Monad (m :: * -> *) where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
他の言語のreturnとは全く異なる
>>=は bindと呼ぶ
a -> m bにm aを入れる為に一旦モナドから値を取り出して渡す感じ
>>って何が嬉しいん?なんのためにあるん?mrsekut.icon
actionから値を取り出して捨て、次のactionに移る
code:hs
test = print 1 >> print 2
main = test2
bindで書くなら
code:hs
test = print 1 >>= \_ -> print 2
do記法で書くなら
code:hs
test = do
print 1 -- _ <- print 1 と同じ。値を捨てている
print 2
PureScriptの場合
code:purs(hs)
class (Applicative m, Bind m) <= Monad m
結果的にはhsと同じモノmrsekut.icon
bindを使っている例
code:hs
-- Maybe
let justInc x = Just (x+1) -- 普通の値を引数に取り、モナドを返す
-- bindがないならこう書いてるだろう
withoutBind = do
x <- Just 3
justInc x
withBind = Just 3 >>= justInc
-- IO
main = do
print =<< return 2
>>を使っている例
code:hs
(Just 3) >> (Just 4) -- Just 4
(Just 3) >>= \_ -> (Just 4) -- 上と同じ
モナド関数a -> m aの関数合成
普通の関数a -> bの関数合成.のモナド関数版
code:hs
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)
モナド関数a -> m aの関数合成
関数合成>>>のモナド関数版
関連する関数
forM
flatMap:: m a -> (a -> m b) -> m b
code:scala
// flatMap :: m a -> (a -> m b) -> m b
// f :: a -> m b
option.flatMap(f)
option match {
case Some(v) => f(v)
case None => None
}
モナドを自作する
HaskellのMonad型クラスの遍歴