Why can `env` be assigned value two times ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Why can `env` be assigned value two times ?

z_axis
defineVar :: Env -> (Id, Val) -> IOThrowsError Val
defineVar envRef (id, val) = do {
    env <- liftIO $ readIORef envRef;
    env <- return $ filter (\(_id, _) -> _id/=id) env; -- clear the current scope
    valRef <- liftIO $ newIORef val;
    liftIO $ writeIORef envRef $ ((id, valRef):env);
    return val;
}

In haskell, the variable canot change its value , right? If so, why can the `env` be assigned value twice?

Sincerely!
e^(π.i) + 1 = 0
Reply | Threaded
Open this post in threaded view
|

Re: Why can `env` be assigned value two times ?

Ross Mellgren
They're two different 'env's, which can be observed by desugaring the do-notation:

do env <- liftIO (readIORef envRef)
   env <- return (filter (\(_id, _) -> _id /= id) env)
...

Desugaring do-notation gets us:

liftIO (readIORef envRev) >>= \ env ->
return (filter (\(_id, _) -> _id /= id) env) >>= \ env ->
...

Sometimes people use different names to make this obvious, e.g.

do env <- liftIO $ readIORef envRef
   env' <- return (filter ... env)

Also note that you're doing a pure operation here, so you don't need two bindings. You could instead do:

do env <- filter (\(_id, _) -> _id /= id) <$> readIORev envRef
...

(<$> is from the supremely useful Control.Applicative, and is equivalent to fmap from Functor, or liftM from Monad)

or:

do env <- liftIO $ readIORef envRef
   let env' = filter ... env

Using let notation here makes it somewhat more obvious that that line doesn't have any side effects.

-Ross

On Nov 15, 2009, at 2:05 AM, zaxis wrote:

>
> defineVar :: Env -> (Id, Val) -> IOThrowsError Val
> defineVar envRef (id, val) = do {
>    env <- liftIO $ readIORef envRef;
>    env <- return $ filter (\(_id, _) -> _id/=id) env; -- clear the current
> scope
>    valRef <- liftIO $ newIORef val;
>    liftIO $ writeIORef envRef $ ((id, valRef):env);
>    return val;
> }
>
> In haskell, the variable canot change its value , right? If so, why can the
> `env` be assigned value twice?
>
> Sincerely!
>
> -----
> fac n = foldr (*) 1 [1..n]
> --
> View this message in context: http://old.nabble.com/Why-can-%60env%60-be-assigned-value-two-times---tp26356073p26356073.html
> Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Why can `env` be assigned value two times ?

Brandon S Allbery KF8NH
In reply to this post by z_axis
On Nov 15, 2009, at 02:05 , zaxis wrote:

> defineVar :: Env -> (Id, Val) -> IOThrowsError Val
> defineVar envRef (id, val) = do {
>    env <- liftIO $ readIORef envRef;
>    env <- return $ filter (\(_id, _) -> _id/=id) env; -- clear the  
> current
> scope
>    valRef <- liftIO $ newIORef val;
>    liftIO $ writeIORef envRef $ ((id, valRef):env);
>    return val;
> }
>
> In haskell, the variable canot change its value , right? If so, why  
> can the
> `env` be assigned value twice?

Because they're not really the same variable; they're separate lambda  
bindings.  If you translate the "do" syntax to the underlying "bind"  
syntax, you get something like:

 > defineVar envRef (id,val) =
 >   liftIO (readIORef envRef) >>=
 >   \env -> return (filter (\(_id,_) -> _id /= id) env) >>=
 >   \env -> liftIO (newIORef val) >>
 >   liftIO (writeIORef envRef ((id,valRef):env)) >>
 >   return val

So you're shadowing (hiding) the original "env" when you reuse the name.

--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

PGP.sig (202 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why can `env` be assigned value two times ?

z_axis
In reply to this post by z_axis
thanks for all your answers !

zaxis wrote
defineVar :: Env -> (Id, Val) -> IOThrowsError Val
defineVar envRef (id, val) = do {
    env <- liftIO $ readIORef envRef;
    env <- return $ filter (\(_id, _) -> _id/=id) env; -- clear the current scope
    valRef <- liftIO $ newIORef val;
    liftIO $ writeIORef envRef $ ((id, valRef):env);
    return val;
}

In haskell, the variable canot change its value , right? If so, why can the `env` be assigned value twice?

Sincerely!
e^(π.i) + 1 = 0