mirror of
https://github.com/thma/LtuPatternFactory.git
synced 2024-12-12 10:42:08 +03:00
adding MonadState example
This commit is contained in:
parent
4c5492ede5
commit
b52d8be513
19
README.md
19
README.md
@ -850,7 +850,8 @@ eval (Let x e1 e2) = eval e1 >>= \v -> -- bind the result of (eval
|
||||
local ((x,v):) (eval e2) -- add (x,v) to the env, eval e2 in the extended env
|
||||
```
|
||||
|
||||
The interesting part here is the helper function `local f m` which applies `f` to the environment and then executes `m` against the (locally) changed environment:
|
||||
The interesting part here is the helper function `local f m` which applies `f` to the environment and then executes `m` against the (locally) changed environment.
|
||||
Providing a locally modified environment as the scope of the evaluation of `e2` is exactly what the `let` binding intends:
|
||||
|
||||
```haskell
|
||||
-- | Executes a computation in a modified environment.
|
||||
@ -872,12 +873,26 @@ interpreterDemo = do
|
||||
(BinOp (*) (Val 2) (Var "x"))
|
||||
print $ runReader (eval exp1) env
|
||||
|
||||
-- an the in GHCi:
|
||||
-- an then in GHCi:
|
||||
|
||||
> interpreterDemo
|
||||
18
|
||||
```
|
||||
|
||||
By virtue of the `local` function we used `MonadReader` as if it provided modifiable state. So for many use cases that require only *local* state modifications its not required to use the somewhat more tricky `MonadState`.
|
||||
|
||||
Writing the interpreter function with a `MonadState` looks like follows:
|
||||
|
||||
```haskell
|
||||
eval1 :: (MonadState (Env a) m) => Exp a -> m a
|
||||
eval1 (Val i) = return i
|
||||
eval1 (Var x) = gets (fetch x)
|
||||
eval1 (BinOp op e1 e2) = liftM2 op (eval1 e1) (eval1 e2)
|
||||
eval1 (Let x e1 e2) = eval1 e1 >>= \v ->
|
||||
modify ((x,v):) >>
|
||||
eval1 e2
|
||||
```
|
||||
|
||||
This section was inspired by ideas presented in [Quick Interpreters with the Reader Monad](https://donsbot.wordpress.com/2006/12/11/quick-interpreters-with-the-reader-monad/).
|
||||
|
||||
[Sourcecode for this section](https://github.com/thma/LtuPatternFactory/blob/master/src/Interpreter.hs)
|
||||
|
@ -31,8 +31,8 @@ eval (Let x e1 e2) = eval e1 >>= \v -> local ((x,v):) (eval e2)
|
||||
|
||||
-- using a State Monad to thread the environment. The Environment can be accessed by get, gets, modify.
|
||||
eval1 :: (MonadState (Env a) m) => Exp a -> m a
|
||||
eval1 (Var x) = gets (fetch x)
|
||||
eval1 (Val i) = return i
|
||||
eval1 (Var x) = gets (fetch x)
|
||||
eval1 (BinOp op e1 e2) = liftM2 op (eval1 e1) (eval1 e2)
|
||||
eval1 (Let x e1 e2) = eval1 e1 >>= \v -> modify ((x,v):) >> eval1 e2
|
||||
|
||||
@ -49,11 +49,9 @@ interpreterDemo = do
|
||||
print $ eval exp env
|
||||
print $ runReader (eval exp) env
|
||||
|
||||
print $ evalState (eval1 exp) env
|
||||
print $ runState (eval1 exp) env
|
||||
|
||||
let exp1 = Let "x"
|
||||
(BinOp (+) (Val 4) (Val 5))
|
||||
(BinOp (*) (Val 2) (Var "x"))
|
||||
let exp1 = Let "x" (BinOp (+) (Val 4) (Val 5)) (BinOp (*) (Val 2) (Var "x"))
|
||||
print $ eval exp1 []
|
||||
|
||||
putStrLn ""
|
||||
|
Loading…
Reference in New Issue
Block a user