Re: Haskell Digest, Vol 52, Issue 1

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

Re: Haskell Digest, Vol 52, Issue 1

Rishiyur Nikhil
Simon Peyton-Jones said:

>  But since the read may block, it matters *when* you perform it.
>  For example if you print "Hello" and then read the IVar, you'll
>  block after printing; but if you read the IVar and then print, the
>  print won't come out.  If the operation was pure (no IO) then you'd
>  have a lot less control over when it happened.

But this is true of any expression in a non-strict language.

Why the special treatment of IVars?

Nikhil


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

Re: Re: Haskell Digest, Vol 52, Issue 1

Simon Marlow-5
Rishiyur Nikhil wrote:

> Simon Peyton-Jones said:
>
>  >  But since the read may block, it matters *when* you perform it.
>  >  For example if you print "Hello" and then read the IVar, you'll
>  >  block after printing; but if you read the IVar and then print, the
>  >  print won't come out.  If the operation was pure (no IO) then you'd
>  >  have a lot less control over when it happened.
>
> But this is true of any expression in a non-strict language.
>
> Why the special treatment of IVars?

Consider this:

  do
     x <- newIVar
     let y = readIVar x
     writeIVar x 3
     print y

(I wrote the let to better illustrate the problem, of course you can inline
y if you want).  Now suppose the compiler decided to evaluate y before the
writeIVar.  What's to prevent it doing that?  Nothing in the Haskell spec,
only implementation convention.  GHC will not transform the program in this
way, because it can have some other undesirable effects.  e.g. see

   http://hackage.haskell.org/trac/ghc/ticket/1592

A pure readIVar would be just like lazy I/O, with similar drawbacks.  With
readIVar, the effect that lets you observe the evaluation order is
writeIVar; with hGetContents it is hClose.  Conclusion: it's probably no
worse than lazy I/O.

Cheers,
        Simon

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

Re: IVar

Jan-Willem Maessen

On Dec 4, 2007, at 8:53 AM, Simon Marlow wrote:

> Rishiyur Nikhil wrote:
>> Simon Peyton-Jones said:
>> >  But since the read may block, it matters *when* you perform it.
>> >  For example if you print "Hello" and then read the IVar, you'll
>> >  block after printing; but if you read the IVar and then print, the
>> >  print won't come out.  If the operation was pure (no IO) then  
>> you'd
>> >  have a lot less control over when it happened.
>> But this is true of any expression in a non-strict language.
>> Why the special treatment of IVars?
>
> Consider this:
>
> do
>    x <- newIVar
>    let y = readIVar x
>    writeIVar x 3
>    print y
>
> (I wrote the let to better illustrate the problem, of course you can  
> inline y if you want).  Now suppose the compiler decided to evaluate  
> y before the writeIVar.  What's to prevent it doing that?  Nothing  
> in the Haskell spec, only implementation convention.

Nope, semantics.  If we have a cyclic dependency, we have to respect  
it---it's just like thunk evaluation order in that respect.  If we  
decide to do the evaluation eagerly, we have to be prepared to bail  
out when the information we require is not available to us.  The  
easiest expedient from GHC's perspective is to perform the evaluation  
lazily, just as we'd expect.

>  GHC will not transform the program in this way, because it can have  
> some other undesirable effects.  e.g. see
>
>  http://hackage.haskell.org/trac/ghc/ticket/1592
>
> A pure readIVar would be just like lazy I/O, with similar  
> drawbacks.  With readIVar, the effect that lets you observe the  
> evaluation order is writeIVar; with hGetContents it is hClose.  
> Conclusion: it's probably no worse than lazy I/O.

Actually, it's considerably better.  The only thing we can observe is  
that the implementation failed to respect the desired semantics (which  
state that computation blocks until the value is available).  That  
causes problems with the strictness properties of I/O, but everything  
to do with the strictness properties of I/O is problematic (because we  
have to decide whether exit = _|_ or not as the above report notes).  
It doesn't, so far as I can see, cause problems with the strictness  
properties of pure computations except that a thread can block in the  
middle of a pure computation waiting for an IVar to fill.  Possibly  
tricky from an RTS perspective, but there's no *semantic* problem.

-Jan

>
>
> Cheers,
> Simon
>
> _______________________________________________
> Haskell mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell

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

Re: Re: Haskell Digest, Vol 52, Issue 1

Taral
In reply to this post by Simon Marlow-5
On 12/4/07, Simon Marlow <[hidden email]> wrote:
>   do
>      x <- newIVar
>      let y = readIVar x
>      writeIVar x 3
>      print y
>
> (I wrote the let to better illustrate the problem, of course you can inline
> y if you want).  Now suppose the compiler decided to evaluate y before the
> writeIVar.  What's to prevent it doing that?

Look at the translation:

newIVar >>= (\x -> let y = readIVar x in writeIVar x 3 >> print y)

y can't be floated out because it depends on x.

--
Taral <[hidden email]>
"Please let me know if there's any further trouble I can give you."
    -- Unknown
_______________________________________________
Haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell