[Haskell-cafe] Stateful iteratees

Ertugrul Soeylemez es at ertes.de
Thu Apr 7 19:35:06 CEST 2011


Gregory Collins <greg at gregorycollins.net> wrote:

> > I'm trying to solve a very practical problem:  I need a stateful
> > iteratee monad transformer.  Explicit state passing is very
> > inconvenient and would destroy the elegance of my library.
> >
> > There are two approaches to this:
> >
> >   1. type MyT a m = Iteratee a (StateT MyConfig m)
> >   2. type MyT a m = StateT MyConfig (Iteratee a m)
> >
> > Both work well except in two very specific corner cases:
> >
> >   - I need to convert the transformer to 'Iteratee a m', i.e. remove
> >     the state layer.  This is obviously trivial with the second
> >     variant, but seems very difficult with the first one, if it's
> >     possible at all.
>
> Why can't you use #1 and do this when you call "run_"?

Because that runs the iteratee and leaves me with a StateT.  Even though
I use a CPS-based StateT, I doubt that it can be converted back to
Iteratee easily.

With the first variant, I would need a function like this:

    runMyApp :: Iteratee a (StateT MyConfig m) b -> Iteratee a m b

I think, this function is impossible to write.  The reason behind this
requirement is that I have multiple monad transformers of this kind,
each in different libraries, each with different state types, and I need
to compose them.

But I have another idea in mind.  I could do the following instead:

    -- First library.
    class Monad m => OneStateMonad m where
        mapOneConfig :: (OneConfig -> OneConfig) -> m OneConfig

    oneComp :: OneStateMonad m => Iteratee Input m Output

    -- Second library.
    class TwoStateMonad m where
        mapTwoConfig :: (TwoConfig -> TwoConfig) -> m TwoConfig

    twoComp :: TwoStateMonad m => Iteratee Input m Output

Then the user of the library has to build the monad transformer stack by
themselves, like this:

    instance Monad m => OneStateMonad (StateT (OneConfig, TwoConfig) m)
    instance Monad m => TwoStateMonad (StateT (OneConfig, TwoConfig) m)

    appComp :: Monad m =>
               Iteratee Input (StateT (OneConfig, TwoConfig) m) Output

That might work, but it seems to be cumbersome.


Greets,
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://ertes.de/





More information about the Haskell-Cafe mailing list