
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