Re: [Haskell] IVars

(moving to haskell-cafe)
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a
non-IO version of succ is unnecessary. My question is why make readIVar a
blocking IO action rather than a blocking pure value, considering that it
always returns the same value?
- Conal
On Dec 8, 2007 11:12 AM, Marc A. Ziegert
many many answers, many guesses... let's compare these semantics:
readIVar :: IVar a -> IO a readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar". but the other way:
readIVar v = return $ readIVar' v
does not work. with this definition, readIVar itself does not block anymore. it's like hGetContents. and...
readIVar v = return $! readIVar' v
evaluates too much: it wont work if the stored value evaluates to 1) undefined or 2) _|_. it may even cause a 3) deadlock:
do writeIVar v (readIVar' w) x<-readIVar v writeIVar w "cat" return x :: IO String
readIVar should only return the 'reference'(internal pointer) to the read object without evaluating it. in other words: readIVar should wait to receive but not look into the received "box"; it may contain a nasty undead werecat of some type. (Schrödinger's Law.)
- marc
Am Freitag, 7. Dezember 2007 schrieb Paul Johnson:
Conal Elliott wrote:
Oh. Simple enough. Thanks.
Another question: why the IO in readIVar :: IVar a -> IO a, instead of just readIVar :: IVar a -> a? After all, won't readIVar iv yield the same result (eventually) every time it's called? Because it won't necessarily yield the same result the next time you run it. This is the same reason the stuff in System.Environment returns values in IO.
Paul. _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell

On Dec 9, 2007 5:09 PM, Conal Elliott
(moving to haskell-cafe)
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering that it always returns the same value?
But I don't think it does. If we're single-threaded, before we writeIVar on it, it "returns" bottom, but afterward it returns whatever what was written. It's a little fuzzy, but that doesn't seem referentially transparent. Luke
- Conal
many many answers, many guesses... let's compare these semantics:
readIVar :: IVar a -> IO a readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the
On Dec 8, 2007 11:12 AM, Marc A. Ziegert
wrote: libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar". but the other way:
readIVar v = return $ readIVar' v
does not work. with this definition, readIVar itself does not block anymore. it's like hGetContents. and...
readIVar v = return $! readIVar' v
evaluates too much: it wont work if the stored value evaluates to 1) undefined or 2) _|_. it may even cause a 3) deadlock:
do writeIVar v (readIVar' w) x<-readIVar v writeIVar w "cat" return x :: IO String
readIVar should only return the 'reference'(internal pointer) to the read object without evaluating it. in other words: readIVar should wait to receive but not look into the received "box"; it may contain a nasty undead werecat of some type. (Schrödinger's Law.)
- marc
Am Freitag, 7. Dezember 2007 schrieb Paul Johnson:
Conal Elliott wrote:
Oh. Simple enough. Thanks.
Another question: why the IO in readIVar :: IVar a -> IO a, instead of just readIVar :: IVar a -> a? After all, won't readIVar iv yield the same result (eventually) every time it's called? Because it won't necessarily yield the same result the next time you run it. This is the same reason the stuff in System.Environment returns values in IO.
Paul.
_______________________________________________ Haskell mailing list Haskell@haskell.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks, Luke. I'd been unconsciously assuming that the IVar would get
written to (if ever) by a thread other than the one doing the reading.
(Even then, there could be a deadlock.)
- Conal
On Dec 9, 2007 9:37 AM, Luke Palmer
On Dec 9, 2007 5:09 PM, Conal Elliott
wrote: (moving to haskell-cafe)
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering that it always returns the same value?
But I don't think it does. If we're single-threaded, before we writeIVar on it, it "returns" bottom, but afterward it returns whatever what was written. It's a little fuzzy, but that doesn't seem referentially transparent.
Luke
- Conal
many many answers, many guesses... let's compare these semantics:
readIVar :: IVar a -> IO a readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the
On Dec 8, 2007 11:12 AM, Marc A. Ziegert
wrote: libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar". but the other way:
readIVar v = return $ readIVar' v
does not work. with this definition, readIVar itself does not block anymore. it's like hGetContents. and...
readIVar v = return $! readIVar' v
evaluates too much: it wont work if the stored value evaluates to 1) undefined or 2) _|_.
it may even cause a 3) deadlock:
do writeIVar v (readIVar' w) x<-readIVar v writeIVar w "cat" return x :: IO String
readIVar should only return the 'reference'(internal pointer) to the read object without evaluating it. in other words: readIVar should wait to receive but not look into the received "box"; it may contain a nasty undead werecat of some type. (Schrödinger's Law.)
- marc
Am Freitag, 7. Dezember 2007 schrieb Paul Johnson:
Conal Elliott wrote:
Oh. Simple enough. Thanks.
Another question: why the IO in readIVar :: IVar a -> IO a, instead of just readIVar :: IVar a -> a? After all, won't readIVar iv yield the same result (eventually) every time it's called? Because it won't necessarily yield the same result the next time you run it. This is the same reason the stuff in System.Environment returns values in IO.
Paul.
_______________________________________________ Haskell mailing list Haskell@haskell.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

I would claim that it's fine to use the type
readIVar :: IVar a -> a
if you're willing to give the "right" semantics to
newIVar :: IO (IVar a)
The semantics is that sometimes when you create an IVar you'll get one that
always returns _|_ when read, sometimes you'll get a proper one. Now if you
happen to read an IVar and it deadlocks your program, well, sorry, you were
unlucky and got a bad IVar that time.
So it's possible to explain away the deadlock as something non-deterministic
in the IO monad. Doing so comes at a terrible price though, because you can
no longer reason about your program.
-- Lennart
On Dec 9, 2007 7:48 PM, Conal Elliott
Thanks, Luke. I'd been unconsciously assuming that the IVar would get written to (if ever) by a thread other than the one doing the reading. (Even then, there could be a deadlock.)
- Conal
On Dec 9, 2007 9:37 AM, Luke Palmer
wrote: On Dec 9, 2007 5:09 PM, Conal Elliott
wrote: (moving to haskell-cafe)
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering that it always returns the same value?
But I don't think it does. If we're single-threaded, before we writeIVar on it, it "returns" bottom, but afterward it returns whatever what was written. It's a little fuzzy, but that doesn't seem referentially transparent.
Luke
- Conal
many many answers, many guesses... let's compare these semantics:
readIVar :: IVar a -> IO a readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the
On Dec 8, 2007 11:12 AM, Marc A. Ziegert
wrote: libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar". but the other way:
readIVar v = return $ readIVar' v
does not work. with this definition, readIVar itself does not block anymore. it's like hGetContents. and...
readIVar v = return $! readIVar' v
evaluates too much: it wont work if the stored value evaluates to 1) undefined or 2) _|_. it may even cause a 3) deadlock:
do writeIVar v (readIVar' w) x<-readIVar v writeIVar w "cat" return x :: IO String
readIVar should only return the 'reference'(internal pointer) to the read object without evaluating it. in other words: readIVar should wait to receive but not look into the received "box"; it may contain a nasty undead werecat of some type. (Schrödinger's Law.)
- marc
Am Freitag, 7. Dezember 2007 schrieb Paul Johnson:
Conal Elliott wrote:
Oh. Simple enough. Thanks.
Another question: why the IO in readIVar :: IVar a -> IO a, instead of just readIVar :: IVar a -> a? After all, won't readIVar iv yield the same result (eventually) every time it's called? Because it won't necessarily yield the same result the next time you run it. This is the same reason the stuff in System.Environmentreturns values in IO.
Paul.
_______________________________________________ Haskell mailing list Haskell@haskell.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Makes sense to me. Giving a formal semantics to the IO version of readIVar
most likely is simpler (taking IO and concurrent IO as given) than the
non-IO version. I didn't understand that before. Thanks for helping me get
it. - Conal
On Dec 9, 2007 12:09 PM, Lennart Augustsson
I would claim that it's fine to use the type readIVar :: IVar a -> a if you're willing to give the "right" semantics to newIVar :: IO (IVar a) The semantics is that sometimes when you create an IVar you'll get one that always returns _|_ when read, sometimes you'll get a proper one. Now if you happen to read an IVar and it deadlocks your program, well, sorry, you were unlucky and got a bad IVar that time.
So it's possible to explain away the deadlock as something non-deterministic in the IO monad. Doing so comes at a terrible price though, because you can no longer reason about your program.
-- Lennart
On Dec 9, 2007 7:48 PM, Conal Elliott
wrote: Thanks, Luke. I'd been unconsciously assuming that the IVar would get written to (if ever) by a thread other than the one doing the reading. (Even then, there could be a deadlock.)
- Conal
On Dec 9, 2007 9:37 AM, Luke Palmer
wrote: (moving to haskell-cafe)
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering
On Dec 9, 2007 5:09 PM, Conal Elliott
wrote: that it always returns the same value?
But I don't think it does. If we're single-threaded, before we writeIVar on it, it "returns" bottom, but afterward it returns whatever what was written. It's a little fuzzy, but that doesn't seem referentially transparent.
Luke
- Conal
many many answers, many guesses... let's compare these semantics:
readIVar :: IVar a -> IO a readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the
but the other way:
readIVar v = return $ readIVar' v
does not work. with this definition, readIVar itself does not block anymore. it's like hGetContents. and...
readIVar v = return $! readIVar' v
evaluates too much: it wont work if the stored value evaluates to 1) undefined or 2) _|_. it may even cause a 3) deadlock:
do writeIVar v (readIVar' w) x<-readIVar v writeIVar w "cat" return x :: IO String
readIVar should only return the 'reference'(internal pointer) to
On Dec 8, 2007 11:12 AM, Marc A. Ziegert
wrote: libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar". the read object without evaluating it. in other words: readIVar should wait to receive but not look into the received "box"; it may contain a nasty undead werecat of some type. (Schrödinger's Law.)
- marc
Am Freitag, 7. Dezember 2007 schrieb Paul Johnson:
Conal Elliott wrote: > Oh. Simple enough. Thanks. > > Another question: why the IO in readIVar :: IVar a -> IO a, instead > of just readIVar :: IVar a -> a? After all, won't readIVar iv yield > the same result (eventually) every time it's called? Because it won't necessarily yield the same result the next time you run it. This is the same reason the stuff in System.Environmentreturns values in IO.
Paul.
_______________________________________________ Haskell mailing list Haskell@haskell.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Conal,
On Dec 9, 2007 6:09 PM, Conal Elliott
readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering that it always returns the same value?
From the rest of Marc's post, I understood the point to be that readIVar lets you do something that readIVar' does not let you do: block until the IVar is written, then continue *without* first evaluating the thunk in the IVar to WHNF. I haven't used IVars myself, so this isn't informed by hands-on experience, but it does sound sensible to me that "block until the IVar has been written" and "evaluate the thunk to WHNF" should be separable.
All the best, - Benja

Thanks. I don't know for what uses of IVars the difference in
expressiveness is helpful, but now I get that the difference is there.
Cheers, - Conal
On Dec 9, 2007 2:08 PM, Benja Fallenstein
Hi Conal,
On Dec 9, 2007 6:09 PM, Conal Elliott
wrote: readIVar' :: IVar a -> a readIVar' = unsafePerformIO . readIVar
so, we do not need readIVar'. it could be a nice addition to the libraries, maybe as "unsafeReadIVar" or "unsafeReadMVar".
The same argument applies any to pure function, doesn't it? For instance, a non-IO version of succ is unnecessary. My question is why make readIVar a blocking IO action rather than a blocking pure value, considering that it always returns the same value?
From the rest of Marc's post, I understood the point to be that readIVar lets you do something that readIVar' does not let you do: block until the IVar is written, then continue *without* first evaluating the thunk in the IVar to WHNF. I haven't used IVars myself, so this isn't informed by hands-on experience, but it does sound sensible to me that "block until the IVar has been written" and "evaluate the thunk to WHNF" should be separable.
All the best, - Benja
participants (4)
-
Benja Fallenstein
-
Conal Elliott
-
Lennart Augustsson
-
Luke Palmer