这是我必须使用的代码:
infixl 9 :@: -- This is newly defined symbol used in the application of expressions
data Expr
= Lit Integer -- a literal
| Var String -- a variable
| Bin Expr Op Expr -- binary operator
| Abs String Expr -- a lambda expression
| Expr :@: Expr -- an application
deriving Show
data Op = Plus | Mult
deriving Show
data Value = IntVal Integer | FunVal Env String Expr
deriving Show
type Env = [(String,Value)]
applyIntOp :: Op -> Value -> Value -> Value
applyIntOp op (IntVal v1) (IntVal v2) =
case op of
Plus -> IntVal (v1 + v2)
Mult -> IntVal (v1 * v2)
eval :: Expr -> Env -> Value
eval (Lit i) env = IntVal i
eval (Var v) env = fromJust (lookup v env)
eval (Bin e1 op e2) env = applyIntOp op (eval e1 env) (eval e2 env)
eval (Abs v b) env = FunVal env v b
eval (ef :@: ea) env = let FunVal env var body = eval ef env
arg = eval ea env
in eval body ((var,arg):env)
目标是制作一个评估函数,使其可以使用变量(变量字符串),其中变量取自环境(Env)。但是,当我尝试使用这些类型中的任何一种来定义monad时,我不能这样做,因为它们的类型不正确(*代替*-> *)。
因此,我将如何定义此Monad,以便可以使用它正确地评估任何表达式。
instance Monad ? where
return = ..
>>= = ..
例如(3 +(x * 4)(apply)(x = 1 + 2)):
eval (Bin (Lit 3) Plus ((Abs "x" (Bin (Var "x") Mult (Lit 4))) :@: Bin (Lit 1) Plus (Lit 2))) []
这将返回15