在Haskell中为循环定义的问题

时间:2010-12-17 19:57:59

标签: haskell for-loop interpreter

我遇到了同样的问题,但也许我可以为我的情况提供一些更多的背景,也许这可以帮助。

使用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'。

我在这里犯了一些愚蠢的错误吗?

2 个答案:

答案 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)