Readerモナド
読み取り専用のStateモナド
グローバル定数を持ち回っている感じ
何処からでもアクセスできるけど、変更はできない
昔はEnvironment Monadと呼ばれていたらしい
Document
型の定義
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
関数モナドのbindの定義に似ているように見える
関数モナドはReaderモナドである
全ての関数が共通の情報を読むから
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するアクション
Stateモナドのgetに相当
runReader :: Reader r a -> r -> a
rが状態、環境
StateモナドのrunStateに相当
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
https://qiita.com/7shi/items/2e9bff5d88302de1a9e9#local
http://yu-i9.hatenablog.com/entry/2014/11/19/235007
https://qiita.com/7shi/items/2e9bff5d88302de1a9e9#local
asks :: MonadReader r m => (r -> a) -> m a
引数の関数を、環境に適応した結果、を返す
MonadReader型クラス
MonadAsk型クラス
ユースケース
ReaderTパターンで言語処理系のenvを作るとき
プログラム内でconfigファイルを参照する
参考
Haskell 状態系モナド 超入門 - Qiita
Haskellで大域変数が欲しい時はReaderモナドを使いましょう - yu-i9.tmp
https://jabaraster.hatenadiary.org/entry/20111107/1320689970
https://mizunashi-mana.github.io/blog/posts/2020/01/use-reader-instead-of-state/
https://xtech.nikkei.com/it/article/COLUMN/20090303/325807/