On Monday 18 October 2010 18:49:41 bearophile wrote: > Jonathan M Davis: > > You can think of a monad as an extra parameter which is passed to each > > function and holds the global state. It isn't a hole in purity at all. > > For instance, it's how Haskell manages to have I/O and yet be > > functionally pure. You don't need the compiler's help to do monads - > > it's just easier if you have it. > > Yet, sooner or later the compiler has to help you giving you a hole to let > the contents of those I/O monads pass though to/from the outside world, > otherwise you will not see any program input/output unless you use > something like a post-mortem debugger :-) So I think the Haskell compiler > has to manage your I/O monads in a special way anyway. Purity can't be > absolute. > > Bye, > bearophile
I've been dealing primarily with D in my free time these days instead of Haskell, so I don't remember all of the details, but the side effects are essentially removed by making the IO part of the output at the end. If there _is_ a hole of some kind in the functional purity of the language it's confined to one point and it does not affect your program overall at all. It would only be when the monad was finally consumed. And many other types of monads don't have anything do to with I/O and _definitely_ don't need any kind of hole in the functional purity of the system. Haskell wouldn't work if it weren't functionally pure (thanks to the fact that it's lazy). Monads were an ingenious solution to the problem of how to deal with stuff like I/O that needs side effects and/or global state without actually allowing either. Monads _do_ end up being a rather viral in that once you have one, pretty much everything in the call chain after that has to pass it along too, but it does allow for functional purity and still allow global state and side effects. Regardless, you can implement basic monads in D just fine without any language support whatsoever. What you basically end up doing is passing around the global state to every function. It's returned as part of the result of the function. Think of passing the global state to every function and having those functions return a tuple of their actual return value and the global state. The caller takes out the actual return value to do whatever it does and passes on the global state variable to the next function that it calls and finally returning it in a tuple along with its own return value. Tuple!(Retval, GlobalState) func(GlobalState gs, otherparams...) { //.... return tuple(retval, gs); } Monads can be a bit hard to wrap your mind around, but they're ingenious. Haskell couldn't really exist without them. - Jonathan M Davis