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.