
1. Learning haskell I discovered that I/O should be avoided nearly 'at all costs'. The problem is that the IO monad is the only one which have more interactive work flow. There is Reader/Writer monad but in fact AFAIU first one is about the environment and second one is about logging. Implementation of Writer can be defined in terms of handles but it is rather limited (either non-full implementation which may be confusing or need of caching the result for pass etc.). I searched the hackage but I didn't find package with pure I/O. Such package may look like: class (Monad m, Monoid v) => MonadInput v m where -- | Gets an element from input (line of text [with \n], 4096 bytes, -- or something like that). mzero on end getChunk :: m v class (Monad m, Monoid v) => MonadOutput v m where -- | Puts an element putChunk :: v -> m () In similar way filters (for example buffered input) can be defined: class (MonadInput v m) => MonadBufferedInput m where -- | If not whole chunk has been consumed at once (for example only -- first 3 elements from list) rest can be returned. It will be -- returned as part of the input on next getChunk call. returnChunk :: v -> m () data (MonadInput v m, Monoid v) => BufferedInputT v m a = BufferedInputT a v Also pipes may be defined (as far as I understand but I'm not 100% sure) which probably will simplify the writing of network tests: -- | Evaluates the first argument. If the getChunk is called the -- evaluation is passed to second argument until the putChunk is -- called, which argument is returned in the first argument callPipeT :: (Monad m, Monoid v) => PipeInputT v m a -> PipeOutputT v m b -> m (a, b) I've started some tests but I'd be grateful for comments (well - probably I'm not the first who come to this idea so a) there is such package or b) my level of Haskell does not allow me to see the problems). 2. I find writing monad transformers annoying. Additionally if package defines transformer A and another transformer B they need to be connected 'by hand'. I find a simple solution which probably is incorrect as it hasn't been used: instance (MonadState s n, Monad (m n), MonadTrans m) => MonadState s (m n) where get = lift get put = lift . put (requires FlexibleInstances MultiParamTypeClasses FlexibleContexts UndecidableInstances - two last are not extensions used by mtl) Regards