Readerモナド
グローバル定数を持ち回っている感じ
何処からでもアクセスできるけど、変更はできない
昔はEnvironment Monadと呼ばれていたらしい 型の定義
code:hs
newtype Reader env a = Reader { runReader :: env -> a }
envは参照したい環境の型
グローバル引数っぽく扱う値の型
実装
code:hs
instance Monad (Reader env) where
return a = Reader (\_ -> a)
Reader f >>= g = Reader $ (\e -> runReader (g (f e)) e)
Maybe aがモナドであるのと同じようにReader rがモナド
bindの定義は以下のようにも書ける
m >>= f = Reader $ \env -> runReader (f (runReader m env)) env
全ての関数が共通の情報を読むから
do式を用いた例
code:hs
-- kは普通の関数
k :: Int -> Int
k = do -- k 3を実行したときの例
a <- (* 2) -- a = 3*2 = 6
b <- (+ 10) -- b = 3+10 = 13
return $ a * b -- 13*6 = 78
k 3を実行した時
*2も+10もreturn $ a * bも引数3を読んでいる
ただし最後のreturnは引き数を読んではいるが、無視している
関数もなどのreturnの定義を参照したらわかる
ask :: MonadReader r m => m r
状態をgetするアクション
runReader :: Reader r a -> r -> a
rが状態、環境
runStateの型はrunState :: State s a -> s -> (a, s)
runReaderの返り値には状態が含まれないことがわかるね
reader :: MonadReader r m => (r -> a) -> m a
関数からReaderモナドを生成する
local :: MonadReader r m => (r -> r) -> m a -> m a
asks :: MonadReader r m => (r -> a) -> m a
引数の関数を、環境に適応した結果、を返す
ユースケース
プログラム内でconfigファイルを参照する
参考