I spend half of my day trying to figure out how to use EitherT as a way to deal with errors in my code.

I have defined a transformer stack like this.

-- Stuff Monad

data StuffConfig = StuffConfig {
  appId     :: T.Text,
  appSecret :: T.Text
}

data StuffState = StuffState {
  stateToken :: Maybe Token,
  stateTime  :: POSIXTime
}

newtype Stuff a = Stuff {
  runStuff :: (ReaderT StuffConfig (StateT StuffState (EitherT T.Text IO))) a
} deriving (Monad, Functor, Applicative, 
            MonadIO, 
            MonadReader StuffConfig,
            MonadState StuffState
            )



askStuff :: StuffConfig -> Stuff a -> IO (Either T.Text a)
askStuff config a = do
  t <- getPOSIXTime 
  runEitherT (evalStateT (runReaderT (runStuff a) config) (StuffState Nothing t))

This works quite well as long as i only use the ReaderT and StateT functions. I am under the impression that now i should be able to write something like this:

faultyFunction :: String -> Stuff String
faultyFunction s = do
  when s == "left" $ left "breaking out"
  "right"

More important is capturing Either return values which should be possible with hoistEither from the errors package:

faultyLookup :: Map -> String -> Stuff String
faultyLookup m k = do
  hoistEither $ lookup k m

I read the real world haskell chapter on monad transformers and fiddled around with lift. But I can't get anything to typecheck.

Edit
Report