Re: concurrency (was OO in Haskell)

1999-10-07 Thread Adrian Hey

On Thu 07 Oct, [EMAIL PROTECTED] wrote:
> See the paper "Concurrent Haskell" by Simon Peyton Jones, Andrew Gordon and
> Sigbjorn Finne, which states:
> 
> "forkIO :: IO () -> IO () forkIO a is an action which takes an action, a, as
> its argument and spawns a concurrent process to perform that action. The I/O
> and other side effects performed by a are interleaved in an unspecified
> fashion with those that follow the forkIO."
> 
> The paper goes on to say:
> 
> "The situation worsens when concurrency is introduced, since now multiple
> concurrent processes are simultaneously mutating a single state. The
> purely-functional state-transformer semantics becomes untenable.

Yes, my opinion seems to be very much in line with yours, and that of
the Concurrent Haskell designers as far as I can see.

Regards
-- 
Adrian Hey







Re: concurrency (was OO in Haskell)

1999-10-07 Thread Manuel M. T. Chakravarty

<[EMAIL PROTECTED]> wrote,

> Manuel M. T. Chakravarty writes:
>  > <[EMAIL PROTECTED]> wrote,
>  > 
>  > > I'm not surprised you are puzzled. Concurrent Haskell, as
>  > > implemented in ghc, does NOT preserve referential
>  > > transparency, nor could it. 
>  > 
>  > Of course it does!  If it wouldn't many of the optimisations
>  > performed by GHC would be invalid and you would be doomed if
>  > you compiled a Concurrent Haskell module with -O (actually,
>  > you would most certainly already be doomed without -O).
>  > 
>  > Check out the type signatures of the `MVar'-related
>  > operations and you will find that they are all nicely
>  > encapsulated in the `IO' monad.  
> 
> That does not help. Encapsulation within the IO monad
> forces MVar operations to be explicitly ordered only
> within the thread in which they occur; it does not effect
> the relative order with respect to MVar operations in
> other threads.

Sure, a program using IO is not necessarily deterministic.

> In summary, Concurrent Haskell only has declarative
> semantics for an individual thread (called a process in
> the paper) - the entire program does *not* have
> declarative semantics i.e it is not referentially
> transparent.

The pure lambda calculus is not the only logic on which you
can base a declarative semantics.  A language based on a
semantics expressed in linear logic won't necessarily be
deterministic, but can be declarative.  Given such a
semantics, there is not necessarily a contradiction to
referential transparency.  Referential transparency means,
IMHO, that you can replace variables by their values
without changing the semantics of the program, ie,

  let x = e1
  in=   [x/e1]e2
  e2

This is still guaranteed in Concurrent Haskell, and it is
guaranteed due to the use of monads.  This does not imply
that the `=' sign above is the equality in a model that is
restricted to deterministic computations.

Manuel






Re: concurrency (was OO in Haskell)

1999-10-07 Thread trb

Manuel M. T. Chakravarty writes:
 > <[EMAIL PROTECTED]> wrote,
 > 
 > > Adrian Hey writes:
 > >  > On Wed 06 Oct, Johan Nordlander wrote:
 > >  > > Just to avoid any unfortunate misconceptions: O'Haskell definitely
 > >  > > preserves the property we commonly refer to as referential transparency,
 > >  > > and so does Concurrent Haskell, or any other sound monadic extension of
 > >  > > the language.
 > >  > 
 > >  > Hmm, I obviously don't understand what 'referential transparency' means.
 > >  > I must say I'm puzzled by statements like this. If the presence of
 > >  > mutable variables (and MVars in Concurrent Haskell) preserve referential
 > >  > transparency, then why _don't_ we have referential transparency in C?
 > > 
 > > I'm not surprised you are puzzled. Concurrent Haskell, as
 > > implemented in ghc, does NOT preserve referential
 > > transparency, nor could it. 
 > 
 > Of course it does!  If it wouldn't many of the optimisations
 > performed by GHC would be invalid and you would be doomed if
 > you compiled a Concurrent Haskell module with -O (actually,
 > you would most certainly already be doomed without -O).
 > 
 > Check out the type signatures of the `MVar'-related
 > operations and you will find that they are all nicely
 > encapsulated in the `IO' monad.  

That does not help. Encapsulation within the IO monad forces MVar operations
to be explicitly ordered only within the thread in which they occur; it does not
effect the relative order with respect to MVar operations in other threads. 

See the paper "Concurrent Haskell" by Simon Peyton Jones, Andrew Gordon and
Sigbjorn Finne, which states:

"forkIO :: IO () -> IO () forkIO a is an action which takes an action, a, as its
argument and spawns a concurrent process to perform that action. The I/O and
other side effects performed by a are interleaved in an unspecified fashion with
those that follow the forkIO."

The paper goes on to say:

"The situation worsens when concurrency is introduced, since now multiple
concurrent processes are simultaneously mutating a single state. The
purely-functional state-transformer semantics becomes untenable.

Instead, we adopt the standard approach to giving the semantics of a concurrent
language, using an operational semantics."

In summary, Concurrent Haskell only has declarative semantics for an individual
thread (called a process in the paper) - the entire program does *not* have
declarative semantics i.e it is not referentially transparent.

For example, consider a program where one thread prints a value from an MVar,
while another thread modifies it. The output of the program will vary from one
run to another, even though its input (none) is unchanged.

Tim






Re: concurrency (was OO in Haskell)

1999-10-07 Thread Christian Sievers

Tim <[EMAIL PROTECTED]> wrote:

> For example, consider a program where one thread prints a value from an MVar,
> while another thread modifies it. The output of the program will vary from one
> run to another, even though its input (none) is unchanged.

This is not a result of using concurrency.
You see the same no input/different output behaviour in a program as
simple as this:

> import Random
> main = getStdRandom (randomR (False,True)) >>= print

(Or use the Time library.)

And nothing of this breakes referential transparency.
For example, 

> main = randomints >>= print
> randomints :: IO (Int,Int)
> randomints = do a <- getStdRandom (randomR (1,100))
> b <- getStdRandom (randomR (1,100))
> return (a,b)

has the same possible results as

> main = randomints >>= print
> randomints :: IO (Int,Int)
> randomints = let rnd = getStdRandom (randomR (1,100)) in
>  do a <- rnd; b <- rnd  
> return (a,b)

Each time a program is run it is given a different world to start
with.
C is as referentially transparent as you are willing to agree that
each function has an implicit IO in its type, which won't gain you
anything. Even that is not really enough. "volatile" variables are
MVars, and what are non-volatile variables changed in signal
handlers? Uncaught type errors? Enough of that.

All the best,
Christian Sievers