我遇到了同样的问题,但也许我可以为我的情况提供一些更多的背景,也许这可以帮助。
使用typedef:
创建解释器interp :: Env -> Expr -> M Val
以这种格式处理循环:
for ( var = expr to expr ) ( expr )
数据构造函数定义如下:
data Val =
ValInt Int
| ValBool Bool
| ValFun (Val -> M Val)
| ValRecFun (Val -> Val -> M Val)
| ValRef Loc
| ValNil
扩展环境定义为:
extendEnv :: Identifier -> Val -> Env -> Env
extendEnv var val (Env bs) = Env ((var,val):bs)
我在这里:
interp env (For x e1 e2 e3) = do
(ValInt v1) <- interp env e1
(ValInt v2) <- interp env e2
if (v1 < v2)
then
let nenv = extendEnv x e1 env in do
interp nenv e3
interp env (For x e1 e2 e3)
else return ValNil
显然,我不想将“e1”传递给for循环的递归调用,而是评估的“v1”变量递增....但我无法弄清楚如何将其传递给正确表达“v1”。这有足够的方向来获得一些帮助吗?:)
好的,这是我尝试创建将执行循环工作的doLoop。我觉得它好像有点过度设计,但我无法弄清楚如何在doLoop中调用“env”而不在调用中传递它。
interp env (For x e1 e2 e3)= do
(ValInt v1) <- interp env e1
(ValInt v2) <- interp env e2
return doLoop x v1 v2 env e3
doLoop :: Identifier -> Int -> Int -> Env-> Expr -> M Val
doLoop x v1 v2 env e3 =
if v1 > v2 then return ValNil
else
let nenv = extendEnv x (ValInt v1) env in
interp nenv e3
doLoop x (ValInt (v1+1)) v2 nenv e3
更新
我的For定义似乎有问题,即:
return doLoop x v1 v2 env e3
它无法匹配预期的类型M Val' against my inferred type
Expr - &gt; M Val'。
我在这里犯了一些愚蠢的错误吗?
答案 0 :(得分:0)
我想你差不多了。看看这个(直接使用Ints,在适当的时候将它们打包到Vals中,修复一些parens的范围问题,并且只在递归调用中传递env):
doLoop :: Identifier -> Int -> Int -> Env -> Expr -> M Val
doLoop x v1 v2 env e3 =
if v1 > v2 then return ValNil
else
let nenv = extendEnv x (ValInt v1) env in
interp nenv e3
doLoop x (ValInt (v1+1)) v2 env e3
答案 1 :(得分:0)
显然,我不想传递“e1” 进入for的递归调用 循环,而是评估“v1” 变量递增....但我不能 弄清楚如何正确传递它 表达“v1”。这够了吗 获得一点帮助的方向?:)
您已经在e1
中获得了变量v1
的'纯'表示,您只需将{1}添加到v1
并重新打包即可。将makeConstExpr
替换为用于构造Expr
的任何内容。
interp env (For var start end body) = do
(ValInt s) <- interp env start
(ValInt e) <- interp env end
if s <= e
then
let envn = extendEnv var (ValInt s) env in do
interp envn body
interp env (For var (makeConstExpr (s + 1)) end body)
else return ValNil
(我好像记得最近打字这个......)
有些人认为最好使用内置函数和元解释器来抽象它。由于这是一项任务,你可能最好不要让它成为非元数据,以增加你对工作力量的理解。
修改:根据您的突变方式,您可能希望在nevn
中传递env
而不是interp env (For var (ValInt (s + 1)) end body)
。