A different
MonadError analogue to the
withExceptT
function. Modify the value (and possibly the type) of an error in an
ExceptT-transformed monad, while stripping the
ExceptT layer.
This is useful for adapting the
MonadError constraint of a
computation.
For example:
data DatabaseError = ...
performDatabaseQuery :: (MonadError DatabaseError m, ...) => m PersistedValue
data AppError
= MkDatabaseError DatabaseError
| ...
app :: (MonadError AppError m, ...) => m ()
Given these types,
performDatabaseQuery cannot be used
directly inside
app, because the error types don't match.
Using
modifyError, an equivalent function with a different
error type can be constructed:
performDatabaseQuery' :: (MonadError AppError m, ...) => m PersistedValue
performDatabaseQuery' = modifyError MkDatabaseError performDatabaseQuery
Since the error types do match,
performDatabaseQuery' _can_
be used in
app, assuming all other constraints carry over.
This works by instantiating the
m in the type of
performDatabaseQuery to
ExceptT DatabaseError m',
which satisfies the
MonadError DatabaseError constraint.
Immediately, the
ExceptT DatabaseError layer is unwrapped,
producing
Either a
DatabaseError or a
PersistedValue. If it's the former, the error is wrapped in
MkDatabaseError and re-thrown in the inner monad, otherwise
the result value is returned.