
Derek Elkins wrote:
The following code works fine for me, so it seems you are missing some details that may help. [...snip code...]
Thank you! Indeed I did simplify the code when writing the message -- because I thought that those other bits could not possibly be at fault... ;-) *trying out many changes to my own code and yours* Ok, I finally found it. What actually made the difference was the case for variables: Your version is
eval (Var x) = gets (fromJust . M.lookup x)
which is suitably lazy, whereas mine was (more or less)
eval e@(Var name) = do env <- ask case M.lookup name env of Nothing -> do -- undefined variable reference warning ("reference to undefined variable " ++ show name) let val = Data "" modify (M.insert name val) return val Just val -> return val
Note that whatever I do in the 'Nothing' case is irrelevant, your code with the Var case replaced by
eval e@(Var name) = do env <- ask case M.lookup name env of Just val -> return val
loops as well. My problem is that I still don't understand why this is so! I know of course that pattern matching is strict, but I thought this should be ok here, since I evaluate the declarations _before_ the body, so when evaluation of the body demands the variable, it will be defined. What am I missing? Cheers Ben