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
21
README.md
21
README.md
@ -850,12 +850,13 @@ 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
|
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
|
```haskell
|
||||||
-- | Executes a computation in a modified environment.
|
-- | Executes a computation in a modified environment.
|
||||||
local :: (r -> r) -- ^ The function to modify the environment.
|
local :: (r -> r) -- ^ The function to modify the environment.
|
||||||
-> m a -- ^ @Reader@ to run in the modified environment.
|
-> m a -- ^ @Reader@ to run in the modified environment.
|
||||||
-> m a
|
-> m a
|
||||||
|
|
||||||
instance MonadReader r ((->) r) where
|
instance MonadReader r ((->) r) where
|
||||||
@ -872,12 +873,26 @@ interpreterDemo = do
|
|||||||
(BinOp (*) (Val 2) (Var "x"))
|
(BinOp (*) (Val 2) (Var "x"))
|
||||||
print $ runReader (eval exp1) env
|
print $ runReader (eval exp1) env
|
||||||
|
|
||||||
-- an the in GHCi:
|
-- an then in GHCi:
|
||||||
|
|
||||||
> interpreterDemo
|
> interpreterDemo
|
||||||
18
|
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/).
|
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)
|
[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.
|
-- 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 :: (MonadState (Env a) m) => Exp a -> m a
|
||||||
eval1 (Var x) = gets (fetch x)
|
|
||||||
eval1 (Val i) = return i
|
eval1 (Val i) = return i
|
||||||
|
eval1 (Var x) = gets (fetch x)
|
||||||
eval1 (BinOp op e1 e2) = liftM2 op (eval1 e1) (eval1 e2)
|
eval1 (BinOp op e1 e2) = liftM2 op (eval1 e1) (eval1 e2)
|
||||||
eval1 (Let x e1 e2) = eval1 e1 >>= \v -> modify ((x,v):) >> 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 $ eval exp env
|
||||||
print $ runReader (eval exp) env
|
print $ runReader (eval exp) env
|
||||||
|
|
||||||
print $ evalState (eval1 exp) env
|
print $ runState (eval1 exp) env
|
||||||
|
|
||||||
let exp1 = Let "x"
|
let exp1 = Let "x" (BinOp (+) (Val 4) (Val 5)) (BinOp (*) (Val 2) (Var "x"))
|
||||||
(BinOp (+) (Val 4) (Val 5))
|
|
||||||
(BinOp (*) (Val 2) (Var "x"))
|
|
||||||
print $ eval exp1 []
|
print $ eval exp1 []
|
||||||
|
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
|
Loading…
Reference in New Issue
Block a user