world as value

P.R. Serrarens pascalrs@cs.kun.nl
Thu, 15 Jul 1999 11:14:28 +0200


Adrian Hey wrote:
> 
> Thank's to Peter Achten and Pascal Serrarens for taking the time to respond
> to my message. I'm a little puzzled by the apparent lack of consensus on this
> issue within the Clean team. I have received messages from several people
> (not Clean Team people) on this issue (privately, not via clean list) who
> are trying to persaude me that the kind of non-determinacy which I would like
> to see in a 'viable' (by my standards) general purpose language is neither
> desirable nor advantageous. This seems to be Peters view, meanwhile Pascal is
> busy introducing non-determinacy into the language (if I understood his
> message).

This is not quite true. I also want to have my functional programs as
deterministic as possible. In fact my early research focussed on determinstic
concurrency. You can get a long way with that, but you cannot do everything.
Some systems are inherently non-deterministic, for example a multi-user
system. Here you have multiple streams of input which are really independent.
As Concurrent Clean is aimed to be a general purpose language for writing
parallel and distributed programs, one cannot ignore this fact. Therefore I
did introduce a construction which may introduce non-determinism, but in a way
where it can be constrolled: if we require the send side of all message
passing channels to be unique, we will have a deterministic system, as
non-determinism is introduced by channels with multiple independent senders on
it. (see the 'Explicit Message Passing' paper for more info)

> If I understand what Pascal and Peter have been saying, the solution to this
> is to design my factory control interface to open new environments or
> channels for each manufacturing activity. I'm not sure this does really
> _solve_ the problem, it just means I have to put the non-determinacy
> somewhere else that isn't a Clean program. Perhaps Pascals 'non-deterministic'
> concurrency would fix this (I believe it would).

The fact it that non-determinsm is not fuctional, as the restult of a
non-deterministic function does not entirely depend on its arguments. Because
of this, we cannot introduce non-determinism in a natural way.
 
> > > The problem is that all IO activity after
> > > doit will be blocked (unnecessarily) until both writesomedata and
> > > dosomethingelse have completed.
> >
> > This may not be a real problem, but more a different way of thinking. The
> > continuation of the main thread is not contained in <dosomthingelse>.
> 
> I don't understand what your saying here. Are you saying that dosomethingelse
> may return a world value before it's actually finished, as if it were a
> 'non-blocking' OS output routine? This is something else I've been wondering
> about. What exactly do we (I) mean by 'finished' as far as IO operations are
> concerned? You don't need to bother answering that one, I'll figure it out
> myself:-)

I think I made a typing error here. What I meant to say was: ... The
continuation of the main thread may be contained in <dosomethingelse>.

Let me make this clear. Suppose we pass all IO activity after <doit> as an
argument to <doit>. This is in general possible, but requires you to write you
programs in a different style. This style is usually references as
'continuation passing style'. You <doit> function would then look like:
(replacing those awful names by shorter ones)

doit :: (*World -> *World) *World -> *World
doit C world =
 let (world1,file1)= openafile world
     file2         = A file1
     world2        = B world1
     world3        = closeafile file2 world2
     world4        = C world3
 in  world4

Here we have 2 dependencies: A -> C and B -> C. Thus, indeed C cannot happen
before A and B have terminated. However we can rewrite <doit> to:

doit :: (*World -> *World) *World -> *World
doit C world =
 let (world1,file1)= openafile world
     file2         = A file1
     world2        = B world1
     world3        = C world2
     world4        = closeafile file2 world2
 in  world4

Now we only have the dependency B -> C. Therefore C can be evaluated
concurrently with A (if B has finished). In other words: all actions after the
<doit> function can be occur independent from the file actions.
 
> > In some cases it may be fine, but when it this so?
> 
> This is a real problem I think. It would be nice if a compiler could figure
> this out, but that seems impossible because it has no real knowledge of the
> effects of actions on environments, nor wether alternative sequences are
> acceptable. It's pretty much down to the programmer to get it right when
> invoking non-deterministic concurrency.

Exactly.
 
-- 
Pascal Serrarens
Concurrent Clean developer
University of Nijmegen, NL