Haskellでevalを作る
evalを作る際は、モナド変換子の話が出てくる
evalは最初からIdentityモナドで実装しておくと後々楽になる
以下のようなものを使うのが一般的な実装
結果を出力する際にIO
envを持ち回る際にReader
エラーメッセージにExcept
ReaderTパターンで言語処理系のenvを作る
モナド変換子(その1: 基本) - Qiita
モナド変換子のtutorial
記事の流れがめちゃくちゃいいmrsekut.icon
step by stepより簡潔
モナド変換子がない世界ではどうしていたかを示し、その辛さを共有
その後、モナド変換子を使ったものを示す
eval関数を「最初からモナドを使う」という想定で実装する
何のモナドを使うかは決めていないが、とりあえず使うことは使うという
なにもないならとりあえずIdentityモナドを使って書いておく
「モナドなし実装」と「モナドあり実装」は結構差があるが、
「Aモナドあり実装」と「Bモナドあり実装」はほぼ変わらない
「Aモナドあり実装」のあとに「Bモナドもほしい」となればモナド変換子で組み合わせる
Monad Transformers Step By Step
モナド変換子の勉強
まず最初に逐次的に書いて、モナド変換子を使ったものに書き換えていく
関数定義と関数適用の実装あり
変数定義はない
第0段階 ref
逐次的に加算や関数を扱えるインタプリタを実装する
https://tnomura9.exblog.jp/27751985/
第1段階 ref
Identityモナドを導入する
https://tnomura9.exblog.jp/27753439/
第2段階 ref
ErrorTを導入する
throwErrorとかする
正しくない式に対してエラーメッセージを表示する
https://tnomura9.exblog.jp/27754823/
第3段階 ref
Envをread onlyにするためにReaderTを導入する
code:hs
runEval2 :: Eval2 a -> Either String a
runEval3 :: Env -> Eval2 a -> Either String a
Envをグローバル定数として持っている感じ
monkey-nimの時みたいにEnvが入れ子にならない
https://tnomura9.exblog.jp/27755922/
第4段階 ref
StateTを導入する
評価のステップ数をカウントするプロファイリング機能を付け加えるために
なので、状態はInteger
ここまでは前段階のモナドを包んでいたが、ここでは包まれる側
ここの上限関係の意味は何?
モナド変換子#5d602192198270000082c162に書いた
https://tnomura9.exblog.jp/27759514/
第5段階 ref
WriterTを導入する
評価中に遭遇した変数名を記録するために
https://tnomura9.exblog.jp/27759554/
第6段階 ref
IOモナドを導入する
IOモナド変換子は定義できないので代わりにIdentityを使っていた所をIOにする
デバッグとかに使える