On 06/30/2011 11:46 PM, Holger Siegel wrote:
> Am 30.06.2011 um 22:57 schrieb Philipp Schneider:
>
>> On 06/30/2011 09:49 PM, Holger Siegel wrote:
>>> (...) But that won't work: After you have evaluated an entry of the 
>>> environment, you store the resulting value but you throw away its updated 
>>> environment. That means, you lose the results of all subcomputations 
>>> instead of propagating them to all other copies of the environment. 
>>> Consider the following expression:
>>>
>>> let x = big_computation in let y = x in y + x
>>>
>>> First, big_computation is bound to the name x, resulting in an environment 
>>> [("x", big_computation)]. Then a closure consisting of this environment 
>>> together with the right hand side 'x' is bound to the name y. Now y+x is 
>>> evaluated: The closure is entered, and from its environment the content of 
>>> x - a call to big_computation - is looked up. Now big_computation is 
>>> evaluated and the result is bound to x in this environment. After that, 
>>> this result is also returned as the value of y. But when returning from the 
>>> evaluation of y, the environment with the updated value of x is lost and 
>>> you have to re-evaluate it in order to calculate x+y!
>> Hello Holger,
>>
>> Can you give me an example of a lambda term in which this would be an issue?
>> Evaluating the following works just fine in my implementation.
>> interp (App (Lam "x" (Add (Var "x") (Var "x"))) big_computation) []
>> When the first variable "x" is evaluated my interp function returns the
>> value and the updated environment. Then to evaluate the second variable
>> the value is just looked up from this environment.
>> Of course in the following big_computation would be evaluated twice
>> (App (Lam "x" (App (Lam "y" (Add (Var "x") (Var "y"))) big_computation))
>> big_computation)
>> But i simply don't have a concept like let x=y.
>
>  App (Lam "x" (App (Lam "y" (Add (Var "y") (Var "x"))) (Var "x" ))) (Con 2)
>
> takes three reduction steps, which is correct, but
>
>  App (Lam "x" (App (Lam "y" (Add (Var "y") (Var "x"))) (Var "x" ))) (Add (Con 
> 1)(Con 1))
>
> takes five reduction steps although it should take only four.
Ok, I now see the problem. Thanks for pointing it out to me.
>
>>> And that is why I say never return an environment. It is either wrong or 
>>> unnecessary or the resulting semantics of the interpreter is hard to 
>>> comprehend.
>>>
>>> In order to implement lazy evaluation correctly, you have to maintain some 
>>> global state in which the thunks are updated. For example, your environment 
>>> could bind IORefs that contain unevaluated thunks to variable names and 
>>> update them when the thunk is evaluated. But then your interpreter has to 
>>> run in the IO monad.
>> I agree that this would  be the "proper" way to do it, but I was trying
>> to minimize the use of monads since they have just been introduced in
>> the course.
> That shouldn't be too hard. Just change your definition of monad M to
>
>  newtype M a = M (State -> IO (a, State))
>
> and define the corresponding monad instance as an exercise :) (or ask me by 
> private mail if you like).
I'll try to implement it tomorrow. Hopefully I'll succeed without your
help. ;)


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to