Skip to content

ClientIO isn't useful. #71

@TravisWhitaker

Description

@TravisWhitaker

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 a

Library 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 = throwError

Functions 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions