-
Notifications
You must be signed in to change notification settings - Fork 26
Description
For better or for worse, the set of exceptions that may be thrown in IO is always open. This makes types like ExceptT e IO a essentially useless. runClientIO can actually return an IO that throws any exception, and checking for Left ClientError is just extra noise. I always use this function when interacting with this library (and all other libraries that use this pattern):
runThrowClientIO :: ClientIO a -> IO a
runThrowClientIO m = do
res <- runExceptT m
case res of Left e -> throwIO e
Right a -> pure aLibrary users can be allowed to migrate away from ClientIO if they choose in a largely backwards-compatible way. The trick is to define a class like this:
class MonadIO m => MonadClient m where
throwClientError :: ClientError -> m a
instance MonadClient IO where
throwClientError = throwIO
instance MonadClient ClientIO where
throwClientError = throwErrorFunctions in the library can then be lifted from ClientIO a to MonadClient m => m a without breaking too much existing code. Users are then free to choose ClientIO, IO, or to provide an instance for whatever monad they're already working in.