Monad型クラス
bind (>>=)とreturnを実装した型
Monadのインスタンスにするためには、Applicativeのインスタンスである必要がある
なのでMonadはApplicative型クラスでありFunctor型クラスでもある
ほんまは
しかしHaskellの歴史的に、最初にFunctorとMonadが導入され、その後にApplicativeが導入されたので、Haskell界の必ずしも全てのMonadがApplicativeというわけではない
が、適切に実装すれば全てのMonadがApplicativeになる
モナド則を満たす
『Monads for functional programming』
モナドがあって何が嬉しいのか
HaskellのいろいろなMonad型クラス
Monadとなる条件
定義側と、使用側で見てみると良いかも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は普通の値からアクションを作る
他の言語のreturnとは全く異なる
Applicative型クラスのpureと同じ
bind (>>=)
>>
PureScriptの場合
code:purs(hs)
class (Applicative m, Bind m) <= Monad m
Bind型クラスを継承する
結果的には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の関数合成
関数合成>>>のモナド関数版
関連する関数
sequence関数
mapM
forM
liftM
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
}
モナドを自作する
ParsecのParserモナドを作る
https://kazu-yamamoto.hatenablog.jp/entry/20080920/1221881130
Rustで実装 ref
TypeScriptで実装 ref
http://m-hiyama.hatenablog.com/entry/20180420/1524187243
https://qiita.com/rooooomania/items/0295d4afb3ad895f5e65
http://www.sampou.org/haskell/a-a-monads/html/index.html
All About Monads
https://qiita.com/mod_poppo/items/8c483951703b5ea0f74e
HaskellのMonad型クラスの遍歴
https://qiita.com/iHdkz/items/e7a59eef034ab6d0fdc2