On 16-Feb-2001 Manuel M. T. Chakravarty wrote:
Elke Kasimir <elke.kasimir@catmint.de> wrote, (...) [...proposal for standardised monad transformers...]
Personally, I would stick with the IO monad.
Beyound personal preference, in my case having an "own" monad has some objective advantages: (a) initialization and clean-up is automatically done in the right places, (b) there are database operations (DML) which should always be performed inside of transaction, and others (DDL) which should be performed outside a transaction. With the help of an (additional) monad context, this is checked at compile time. (c) with an additional context for transactions, unadvertantly nesting of transactions is detected at runtime.
As you have illustrated, a rather heavy mechanism is needed for combining state transformers and your are getting into rather complicated overloading and typing issues. The result of which are at least that when a user of your library gets a type error, it will probably be cluttered with cryptic contexts and such.
There is surely the possibility of tricky errors when initially setting up the desired context. In the rest of the program, typing issues and type errors should be rather simple, as functions using the library always have function results of type: (Io m, Gui a, Db m) => m a (where some of the contexts may be sometimes ommitted), which I find rather intuitive and tranparent.
The from a functional programming point of view certainly ugly, but, on the other hand, very pragmatic solution is to have your database library use `IORef's to maintain your global state.
It is even acceptable for me to manage the state in C - independent of the API design - but then some time there will be the question: Why do I always say that that Haskell is the better programming language, when I'm really doing all the tricky stuff in C?...
Then, all your operations can work in the plain IO monad and you have no problem combining with other libraries using the IO monad. In fact, it is actually possible to argue that this is a clean solution, because all you are doing is to extend the state maintained by the IO monad.
Given that IO represents the "state of the world", at least parts of "my" state (which represents state outside of Haskell) have a natural right to reside in IO. But going back to software design issues, what IO actually does not is representing the state of the world in a pretty modular fashion. Consequences: Given that here on the mailing list there is the opinion that "sticking to IO" is to be preferred, and that a "monad composition" approach requires measures beyound one single library, I should probably offer both solutions, the "sticking to IO" solution being the standard, and the other being declared experimental. Elke.
Cheers, Manuel
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
--- "If you have nothing to say, don't do it here..." Elke Kasimir Skalitzer Str. 79 10997 Berlin (Germany) fon: +49 (030) 612 852 16 mail: elke.kasimir@catmint.de> see: <http://www.catmint.de/elke> for pgp public key see: <http://www.catmint.de/elke/pgp_signature.html>