Problem With Defined For Loop in Haskell
I have come across the same problem, but m开发者_运维技巧aybe I can give a little more context in what is going on for my situation and maybe that can help.
Creating an interpreter with typedef:
interp :: Env -> Expr -> M Val
that handles for loops in this format:
for ( var = expr to expr ) ( expr )
Data constructor defined as the following:
data Val =
ValInt Int
| ValBool Bool
| ValFun (Val -> M Val)
| ValRecFun (Val -> Val -> M Val)
| ValRef Loc
| ValNil
And an extended environment defined as:
extendEnv :: Identifier -> Val -> Env -> Env
extendEnv var val (Env bs) = Env ((var,val):bs)
Here's where I am:
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
Obviously, I don't want to pass "e1" into the recursive call of the for loop, but rather the evaluated "v1" variable incremented.... but I can't figure out how to pass it the correct expression of "v1". Is this enough direction to get a little help?:)
*UPDATE*
Ok, here's my attempt at creating the doLoop that will do my looping work. I feel as if it is a little over-engineered, but I could not figure out how to call the "env" in doLoop without passing it in the call.
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
UPDATE
It seems to be having a problem with my For definition, namely:
return doLoop x v1 v2 env e3
It can't match the expected type M Val' against my inferred type
Expr -> M Val'.
Am I making some silly error here?
Obviously, I don't want to pass "e1" into the recursive call of the for loop, but rather the evaluated "v1" variable incremented.... but I can't figure out how to pass it the correct expression of "v1". Is this enough direction to get a little help?:)
You've already got the 'pure' representation of the variable e1
in v1
, you can simply add 1 to v1
and repack it. Replace makeConstExpr
with whatever it is you use to construct an 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
(I seem to recall typing this recently...)
Some would argue that it's better to abstract this using built in functions and making a meta-interpreter. As this is an assignment, you're probably better off making it as non-meta as possible to increase your understanding of the forces at work.
Edit: Depending on how you're doing your mutation, you may want to pass nevn
instead of env
in interp env (For var (ValInt (s + 1)) end body)
.
I think you're almost there. Take a look at this (working with Ints directly, packing them into Vals when appropriate, fixed a little scoping issue with parens, and only passing env in the recursive call):
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
精彩评论