[Haskell-cafe] Monad Input/Output and Monad Transformers

Maciej Piechotka uzytkownik2 at gmail.com
Thu Jul 2 07:31:59 EDT 2009


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



More information about the Haskell-Cafe mailing list