A servant-server Handler is a newtype wrapper over an ExceptT
, and has instances for MonadThrow
, MonadCatch
, MonadError
, etc.
This might be a somewhat contrived example, but it shows an issue I often face:
In a handler I want to call three functions that return Either String Int
, then perform a computation of type Int -> Int -> Int -> IO (Either SomeError Text)
, taking the three Int
s from before.
How should I structure this code to ensure that an error is returned as early as possible?
I see that I can use Either
's Monad
instance to “collapse” the first three Either String Int
computations into e.g. Either String (Int,Int,Int)
, and then binding the IO
computation to some result value and then use case
to decide whether to return a successful result or use throwError
to throw the SomeError
type (after a conversion?), but I was hoping to be able to something like the following:
f, g, h :: Either String Int
a :: Int -> Int -> Int -> IO (Either SomeError Text)
myHandler :: Handler Text
myHandler = do
x1 <- f
x2 <- g
x3 <- h
liftIO $ convertError $ (a x1 x2 x3)
Is it possible to write it similar to the code above?
Handler
is anExceptT ServantErr
, but your errors areString
s. Can we assume you have a functionString -> ServantErr
that you can use to convert the errors? – Hedden