[Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

2004-11-26 Thread Ian . Stark
On Fri, 26 Nov 2004, George Russell wrote:

 Ian Stark wrote (snipped):
   Way back in this thread, Koen Claessen mentioned the idea of a commutative
   version of the IO monad for handling things with identity.  That doesn't 
 quite
   do it, but I have a refinement that might.  The thing is to focus on IO
   computations that are:
  
a) central -- their effect commutes with every other IO action
b) affine  -- their effect is not directly observable, and can be 
 discarded.

 Unfortunately I have a number of examples where I use global variables with
 initialisation actions which cannot conceivably be proven to be central  
 affine
 by the compiler.  For example, where I want to call up an external program 
 (such
 as wish) which I will later use for doing graphics.

This indeed can't be proved central+affine, because it isn't.  So instead,
choose one of the following:

1 (Good) Indirection:

  declare gc - newIORef None; so that gc is a global variable holding a
  (Maybe GraphicsContext).  Initialise the contents in your main IO
  action; and then pull out the value any time you need to look at it.

  Yes, you need to explicitly initialise it; but you don't need then to
  pass the initialized handle all around your code.  The painful plumbing
  goes away.


2 (Neutral) As above, but write getGC :: IO GraphicsContext that looks in
  gc, and if there is None then calls out to wish, or whatever, to
  initialise it first.

  Sound, but getGC then hides some wildly varying behaviour.


3 (Evil) Give in to the dark side.  Have unsafeIOtoACIO, write a
  declaration using it, and hope that your compiler does the easy thing
  and executes all declarations at the start of the program.

  In fact not much worse than (2); only now the possible effect points
  have leapt from all uses of gc to all uses of IO.


 The Haskell libraries would run into a similar problem when they tried to
 open stdin/stdout/stderr.

But they don't open them, right?  The whole point of stdin/stdout/stderr
being fixed integers is that these handles are already opened when the
program starts.


 Or indeed when they tried to implement RandomGen, which I presume is
 going to want to get at the system clock to seed the random number
 generator.

Yes, the system StdGen really does have to get initialised.  But the
presumed readRandomNumberFromSystem() is ACIO if it's random (OK, so if
it's implemented by opening /dev/random, then this would have to be
wrapped in assertIOisACIO).

--
Ian Stark   http://www.ed.ac.uk/~stark
LFCS, School of Informatics, The University of Edinburgh, Scotland
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

2004-11-26 Thread George Russell
[EMAIL PROTECTED] wrote:
(initialising by wish)
This indeed can't be proved central+affine, because it isn't.  So instead,
choose one of the following:
 1 (Good) Indirection:
   declare gc - newIORef None; so that gc is a global variable holding a
  (Maybe GraphicsContext).  Initialise the contents in your main IO
  action; and then pull out the value any time you need to look at it.

  Yes, you need to explicitly initialise it; but you don't need then to
  pass the initialized handle all around your code.  The painful plumbing
  goes away.
I think this is either unwieldy or inefficient. Imagine a large library
containing lots of these things which need to be initialised if used.  Then
I predict that one of two things will happen
(a) people will end up writing boilerplace code at the start of the main
action which does
   initialise1
   initialise2
   ... blah blah ...
(b) (more likely).  There will be a single initialisation function for the
library, which initialises everything, even the stuff you don't actually
want.
2 (Neutral) As above, but write getGC :: IO GraphicsContext that looks in
  gc, and if there is None then calls out to wish, or whatever, to
  initialise it first.
  Sound, but getGC then hides some wildly varying behaviour.
I think this is basically what my Data.GlobalVariables module does,
except that most of the work is done for you and you also get the
bonus of being able to create fresh worlds within your program (so
that two copies of main can be run concurrently, for example).


3 (Evil) Give in to the dark side.  Have unsafeIOtoACIO, write a
  declaration using it, and hope that your compiler does the easy thing
  and executes all declarations at the start of the program.
  In fact not much worse than (2); only now the possible effect points
  have leapt from all uses of gc to all uses of IO.
The real danger of unsafeIOtoACIO is that a compiler may well choose
to implement ACIO declarations by only initialising variables when
they are actually needed.  Thus possible effect points will not just
be all uses of IO, but everywhere in the program.
But they don't open them, right?  The whole point of stdin/stdout/stderr
being fixed integers is that these handles are already opened when the
program starts.
Surely not?  Haskell buffers have to be initialised and so on.
Yes, the system StdGen really does have to get initialised.  But the
presumed readRandomNumberFromSystem() is ACIO if it's random (OK, so if
it's implemented by opening /dev/random, then this would have to be
wrapped in assertIOisACIO).
So assertIOisACIO will have to exist, if only in an internal GHC module ...
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

2004-11-26 Thread Jules Bean
On 26 Nov 2004, at 12:08, George Russell wrote:
  Yes, you need to explicitly initialise it; but you don't need then 
to
  pass the initialized handle all around your code.  The painful 
plumbing
  goes away.
I think this is either unwieldy or inefficient. Imagine a large library
containing lots of these things which need to be initialised if used.  
Then
I predict that one of two things will happen
(a) people will end up writing boilerplace code at the start of the 
main
action which does
   initialise1
   initialise2
   ... blah blah ...
(b) (more likely).  There will be a single initialisation function for 
the
library, which initialises everything, even the stuff you don't 
actually
want.

To me this seems perfectly fine. Ian's proposal gets us TWIs, which I 
can see the need for. Implicit initialisation (i.e. stateful 
initialisation functions happening non-deterministicly, like java 
static{} blocks or C++'s similar feature) is a can of worms I currently 
see no value in opening.

Jules
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

2004-11-26 Thread Ian . Stark
On Fri, 26 Nov 2004, Jules Bean wrote:
On 26 Nov 2004, at 12:08, George Russell wrote:
  Yes, you need to explicitly initialise it; but you don't need then to
  pass the initialized handle all around your code.  The painful plumbing
  goes away.
I think this is either unwieldy or inefficient. Imagine a large library
containing lots of these things which need to be initialised if used.  Then
I predict that one of two things will happen
(a) people will end up writing boilerplace code at the start of the main
action which does
   initialise1
   initialise2
   ... blah blah ...
(b) (more likely).  There will be a single initialisation function for the
library, which initialises everything, even the stuff you don't 
actually
want.
To me this seems perfectly fine. Ian's proposal gets us TWIs, which I can see 
the need for. Implicit initialisation (i.e. stateful initialisation functions 
happening non-deterministicly, like java static{} blocks or C++'s similar 
feature) is a can of worms I currently see no value in opening.
It's true that ACIO only does some things: and that includes global 
variables initialized with values.  I think that's pretty useful; but 
it's true that we don't get initializing with arbitrary IO activity.

Even when you do want to open the can of worms, things are better: 
unsafePerformIO needs an accompanying NOINLINE pragma, whereas pushing 
things through assertIOisACIO will guarantee execution no more than once.

I.
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

2004-11-25 Thread George Russell
Ian Stark wrote (snipped):
 Way back in this thread, Koen Claessen mentioned the idea of a commutative
 version of the IO monad for handling things with identity.  That doesn't quite
 do it, but I have a refinement that might.  The thing is to focus on IO
 computations that are:

  a) central -- their effect commutes with every other IO action
  b) affine  -- their effect is not directly observable, and can be discarded.
Unfortunately I have a number of examples where I use global variables with
initialisation actions which cannot conceivably be proven to be central  affine
by the compiler.  For example, where I want to call up an external program (such
as wish) which I will later use for doing graphics.
The Haskell libraries would run into a similar problem when they tried to
open stdin/stdout/stderr.  Or indeed when they tried to implement RandomGen,
which I presume is going to want to get at the system clock to seed the
random number generator.
My guess is that if we were to have top-level - actions where the actions were
restricted to those certified to be ACIO, it would not be very long before GHC
would implement an unsafeForceACIO function ...
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe