[Haskell-beginners] Lifting (Either SqlError a) in a monad stack

Bryan Vicknair bryanvick at gmail.com
Mon Aug 26 23:05:00 CEST 2013

I'm at the beginning of the monad transformers journey, and this is stumping
me. I've read "Monad Transformers Step by Step" which made me confident enough
to play with simple stacks, but I'm a bit lost in the following example from
work. Please excuse any incorrect transformer terminology.

In a WAI web app, I want to chain these two actions inside a monad stack:

> safeConnect :: ConnectInfo         -> IO (Either SqlError Connection)
> safeInsert  :: Thing -> Connection -> IO (Either SqlError Id)

Here is an example where I would like 'result' to be (Right Id) only if the DB
connection *and* the insert were successful, (Left SqlError) otherwise.

> add :: Request -> ResourceT IO Response
> add _ = do
>   result <- liftIO $ safeConnect devConnInfo >>= safeInsert thing
>   case result of
>     (Left e)  -> return $ dbErr e
>     (Right _) -> return $ postRedirect
>   where thing = exampleThing

The compiler tells me (edited for brevity):

    Expected type: Either SqlError Connection -> GHC.Types.IO a0
      Actual type: Connection -> GHC.Types.IO (Either SqlError Id)
    In the return type of a call of `safeInsert'
    In the second argument of `(>>=)', namely
      `safeInsert thing'

How can I chain safeConnect and safeInsert using the (Either SqlError a) monad
inside WAI's (ResourceT IO Response) monad stack?

More information about the Beginners mailing list