RE: [Haskell-cafe] Re: [Haskell] Re: Global Variables and IOinitializers
On Mon, 29 Nov 2004, Simon Peyton-Jones wrote: This unfortunate observabilty of an ordering (or hash value) that is needed only for efficient finite maps, is very annoying. I wish I knew a way round it. As it is we can pick a) expose Ord/Hash, but have unpredictable results b) not have Ord/Hash, but have inefficient maps I was going to ask what was wrong with doing the tedious: class FiniteMappable key where listToFM :: [(key,elt)] - FiniteMap key elt addToFM :: FiniteMap key elt - key - elt - FiniteMap key elt ...etc etc... with the possibility of: instance Ord key = FiniteMappable key where listToFM = listToFMoriginal ...etc etc... where one would only export the fact that a particular type is FiniteMappable, not Ord. But then I remembered that modules can't hide instance declarations, so that's no good. :-( Is there some way to insert a newtype, so that just one instance becomes visible? -- 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
Re: [Haskell-cafe] Execution Contexts
On Sat, 27 Nov 2004, Benjamin Franksen wrote: I would think that with ACIO we have a nice mathematical characterization for the IO actions that would be safe even at the top-level. (Safe meaning mainly that we do not open a can-of-worms with regard to execution order.) I don't know how easy or hard it is to prove of a certain IO action that is in fact in ACIO. Hard, because it depends on observational equivalence of IO effects, and for that you need a semantics for the RealWorld. Maybe a better way to treat it is that whereas doing an IO action puts it in an execution trace at a specific point, doing an ACIO action is simply perform this some time, maybe, if required. Giving something like newUnique an ACIO type indicates that semantics is sufficient; whereas for readIORef it typically isn't, and you want the stronger guarantee of an IO type. This breaks down as soon as the IO action does a forkIO. Isn't sharing global variables the correct semantics for forkIO ? That explicitly creates a 'lightweight' thread, which shares execution context with its invoker. I agree that forkOS, with its own local context, is harder. I suspect that, yes, as soon as you want to have more than one execution context simultaneously, then you need to manage them. For which XIO seems to do the job. Ian -- 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
Re: [Haskell-cafe] Execution Contexts
Ben, On Sat, 27 Nov 2004, Benjamin Franksen wrote (apropos ACIO topdecls): ... a highly controversial new language feature. The language feature is easily done, and just what has been happening all along: type ACIO = IO declare :: ACIO a - a {-# NOINLINE declare #-} declare e = unsafePerformIO e All 'affine central' does is give a label to one particular idiomatic use of IO. The controversial part would be wading through libraries arguing over what things were ACIO. OK, I admit it would be nice if the compiler would manage everything, use - syntax, and take advantage of affine central actions being well-behaved. But not vital. Ian ___ 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
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
Re: [Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad
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
Re: [Haskell-cafe] Yet another IO initializer: Effectful declarations and an ACIO monad
On Thu, 25 Nov 2004, Jules Bean wrote: On 25 Nov 2004, at 10:07, [EMAIL PROTECTED] wrote: Thus an element u of (IO a) is affine central if for all v::IO b and w::IO c, do { x - u; v } = v(affine) If x does not occur in v, I presume? Yes, and similarly for centrality: do { x - u; y -v; w } = do { y - v; x - u; w } (central) applies only when x not free in v and y not free in u. This means that ACIO computations can be rearranged and discarded, but only within the limits of dataflow dependencies between the values. Working out these dependencies are the job of a compiler, exactly as with standard value declarations in Haskell. I think it should even be possible to have mutually recursive ACIO declarations, provided non-strict constructors intervene. Ian ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe