Skip to content

Commit 4b7ff9e

Browse files
committed
[monad-transformers] add
1 parent 395954f commit 4b7ff9e

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

monad-transformers/Main.hs

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
module Transformers where
2+
3+
import Control.Monad.Identity
4+
import Control.Monad.Except
5+
import Control.Monad.Reader
6+
import Control.Monad.State
7+
import Control.Monad.Writer
8+
import Data.Maybe
9+
import qualified Data.Map as Map
10+
11+
type Name = String
12+
data Exp = Lit Integer
13+
| Var Name
14+
| Plus Exp Exp
15+
| Abs Name Exp
16+
| App Exp Exp
17+
deriving (Show)
18+
19+
data Value = IntVal Integer
20+
| FunVal Env Name Exp
21+
deriving (Show)
22+
23+
type Env = Map.Map Name Value
24+
25+
eval0 :: Env -> Exp -> Value
26+
eval0 env (Lit i) = IntVal i
27+
eval0 env (Var n) = fromJust (Map.lookup n env)
28+
eval0 env (Plus e1 e2) = let IntVal i1 = eval0 env e1
29+
IntVal i2 = eval0 env e2
30+
in IntVal (i1 + i2)
31+
eval0 env (Abs n e) = FunVal env n e
32+
eval0 env (App e1 e2) = let val1 = eval0 env e1
33+
val2 = eval0 env e2
34+
in case val1 of
35+
FunVal env' n body -> eval0 (Map.insert n val2 env') body
36+
37+
type Eval1 a = Identity a
38+
39+
runEval1 :: Eval1 a -> a
40+
runEval1 ev = runIdentity ev
41+
42+
eval1 :: Env -> Exp -> Eval1 Value
43+
eval1 env (Lit i) = return $ IntVal i
44+
eval1 env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env
45+
eval1 env (Plus e1 e2) = do val1 <- eval1 env e1
46+
val2 <- eval1 env e2
47+
case (val1, val2) of
48+
(IntVal i1, IntVal i2) ->
49+
return $ IntVal (i1 + i2)
50+
eval1 env (Abs n e) = return $ FunVal env n e
51+
eval1 env (App e1 e2) = do val1 <- eval1 env e1
52+
val2 <- eval1 env e2
53+
case val1 of
54+
FunVal env' n body ->
55+
eval1 (Map.insert n val2 env') body
56+
57+
type Eval2 a = ExceptT String Identity a
58+
59+
runEval2 :: Eval2 a -> Either String a
60+
runEval2 ev = runIdentity (runExceptT ev)
61+
62+
eval2a :: Env -> Exp -> Eval2 Value
63+
eval2a env (Lit i) = return $ IntVal i
64+
eval2a env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env
65+
eval2a env (Plus e1 e2) = do val1 <- eval2a env e1
66+
val2 <- eval2a env e2
67+
case (val1, val2) of
68+
(IntVal i1, IntVal i2) ->
69+
return $ IntVal (i1 + i2)
70+
eval2a env (Abs n e) = return $ FunVal env n e
71+
eval2a env (App e1 e2) = do val1 <- eval2a env e1
72+
val2 <- eval2a env e2
73+
case val1 of
74+
FunVal env' n body ->
75+
eval2a (Map.insert n val2 env') body
76+
77+
eval2b :: Env -> Exp -> Eval2 Value
78+
eval2b env (Lit i) = return $ IntVal i
79+
eval2b env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env
80+
eval2b env (Plus e1 e2) = do val1 <- eval2b env e1
81+
val2 <- eval2b env e2
82+
case (val1, val2) of
83+
(IntVal i1, IntVal i2) ->
84+
return $ IntVal (i1 + i2)
85+
_ -> throwError "type error: IntVal expected"
86+
eval2b env (Abs n e) = return $ FunVal env n e
87+
eval2b env (App e1 e2) = do val1 <- eval2b env e1
88+
val2 <- eval2b env e2
89+
case val1 of
90+
FunVal env' n body ->
91+
eval2b (Map.insert n val2 env') body
92+
_ -> throwError "type error: FunVal expected"

monad-transformers/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# monad-transformers
2+
3+
* 参考文献
4+
* [Monad Transformers Step by Step](https://page.mi.fu-berlin.de/scravy/realworldhaskell/materialien/monad-transformers-step-by-step.pdf)

0 commit comments

Comments
 (0)