[Haskell-beginners] Learning StateT

Brent Yorgey byorgey at seas.upenn.edu
Sat Nov 27 08:35:30 EST 2010

On Sat, Nov 27, 2010 at 10:22:39AM +0100, Tim Baumgartner wrote:
> Hi Haskellers,
> in order to learn Monad Transformers, I'm trying to write a simple
> calculator that has an internal state of type Calc that is modified
> after each line the user enters. I started like this:
> main :: IO ()
> handleLine :: StateT Calc IO Bool   -- return's False in order to exit
> main uses runState in order to extract the action it needs from the
> transformer. Up to this point, it works fine. But in order to separate
> I/O and parsing, I'd prefer to have another function
> processInput :: String -> State Calc (Maybe String)

Separating I/O and parsing like this is a great idea.  Unfortunately,
from an engineering point of view, making different monad stacks work
together can be difficult (as you have discovered).  As I see it you
have three options (in increasing order of both desirability and

  1) Give up separating I/O and parsing, and just rewrite processInput
     to be in the StateT Calc IO monad.

  2) Write an adapter function

       withoutIO :: State s a -> StateT s IO a

     which makes a State s computation into a StateT s IO computation
     (which is guaranteed to do no I/O).  The implementation of
     withoutIO will probably involve runState, but it will be able to
     properly thread the state through from previous computations.

  3) Rewrite everything in a "capabilities" style, e.g. instead of the
     concrete type  StateT Calc IO Bool you would have

       (MonadState Calc m, MonadIO m) => m Bool

     and so on, which allows for much easier mixing of different
     concrete monad stacks.

Ultimately, (3) seems to me like the "right" way to do this sort of
thing.  It definitely runs into limitations as well, although many of
them can be mitigated by technology found in the Monatron package
(which unfortunately at the moment is woefully undocumented).


More information about the Beginners mailing list