Benjamin Franksen wrote: | 1) I strongly disagree with ideas to execute IO actions | implicitly in whatever defined or undefined sequence | before or during main for whatever reasons.
I agree with the objections you make. Having full IO actions as initialization actions might be a bit too much. | What I originally wanted to propose was therefore some | sort of source-to-source program transformation that adds | all the intermediate extra function arguments. Then I | realized that this is almost exactly what the so called | 'implicit parameters' extension to Haskell is all about, | and that using them as a replacement for global variables | has already been proposed by John Hughes. The problem with John's approach is that it breaks modularity. It does this in two ways: (1) Whenever a module uses an implicit parameter like that, it has to have a name that is different from all implicit parameters used by any other (future) module. (Yes, implicit paramers cannot be quantified by a module name.) This is difficult to ensure. (2) Having the implicit parameter breaks the abstraction barrier. I might want to re-implement a module that does not make use of global variables, into one that uses a cache or hash-table or whatever (think BDD library), and not change the interface of the functions that are provided. | What I've been asking myself is: Wouldn't it be possible | for the compiler to silenty add the implicit parameter | type constraints behind the scenes? You would be back at square 1, since your program will still look and behave exactly the same as a program that implicitly executes all initializations; the only difference is implementation. I have a different proposal. Imagine a commutative monad, CIO. Commutative monads have the property that it does not matter in what order actions are performed, they will have the same effect. In other words, for all m1 :: CIO A, m2 :: CIO B, k :: A -> B -> CIO C, it should hold that: do a <- m1 do b <- m2 b <- m2 === a <- m1 k a b k a b Now, one could imagine an extension X of Haskell98, in which modules are allowed to contain definitions of the form: p <- m Here, p is a (monomorphic) pattern, and m is of type CIO A, for some type A. CIO is an (abstract) monad provided in a library module, just like IO is today. One could wonder where the primitive actions in the monad CIO come from? Well, library providers (compilers) could provide these. For example: newIORefCIO :: a -> CIO (IORef a) newEmptyMVarCIO :: CIO (MVar a) And so on. The implementer of these functions has to guarantee that the actions do not destroy the commutativity of the CIO monad. This is done in the same way as today, compiler writers and users of the FFI guarantee that certain primitive operations such as + on Ints are pure. The FFI could even adapt CIO as a possible result type (instead of having just pure functions or IO functions in the FFI). (One could even imagine a compiler feature that provides us with a function: unsafeIOtoCIO :: IO a -> CIO a But this could of course never be a part of the official Haskell98 extension X!) Comments welcome. Kind regards, /Koen _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell