Something I am working on at the minute, and I would appreciate some thoughts on the best way to model this.
I generating stubs for AWS services. Each service has a set of errors it can return. For example:
ServiceException
ResourceNotFoundException
ResourceConflictException
TooManyRequestsException
InvalidParameterValueException
PolicyLengthExceededException
PreconditionFailedException
Now each endpoint within the service might only be able to return some of these errors. It would be more accurate if each endpoints type only allows for the errors it can return, and not the full set.
Anyway, here are the options I have thought of so far:
- Have each endpoints return type allow the full set:
type ServiceError
= ServiceException
| ResourceNotFoundException
| ResourceConflictException
| TooManyRequestsException
| InvalidParameterValueException
| PolicyLengthExceededException
| PreconditionFailedException
enpoint1 : Input1 -> Request (Result ServiceError Response1)
endpoint2 : Input2 -> Request (Result ServiceError Response2)
Problem with this is, suppose endpoint1 can only produce ResourceNotFoundException
and not the other errors, its return type is overly wide.
- Have each endpoints return type allow just the errors it can return. This seems to need an error type per endpoint:
type Endpoint1Error
= Endpoint1ErrorResourceNotFoundException
service1 : Input1 -> Request (Result Endpoint1Error Response1)
type Endpoint2Error
= Endpoint2ErrorServiceException
| Endpoint2ErrorResourceNotFoundException
| Endpoint2ErrorResourceConflictException
| Endpoint2ErrorTooManyRequestsException
service2 : Input2 -> Request (Result Endpoint2Error Response2)
Problem with this approach is the need to have an error type per endpoint. This removes the ablity to andThen
a series of endpoint calls together without mapping the errors onto some other error type that includes all the possiblities (ServiceError
and a load of error mapping functions). I also had to prefix all the constructors with EndpointX
to make their names unique.
-
Do something with phantom types. Seems overly complicated for this.
-
Maybe just return the error name as a
String
. Its simple and the full set of strings could be supplied as constants to reduce coding errors when writing an error matching case statement:
case error of
AWS.Lambda.policyLengthExceeedException -> ...
_ -> ...
Any better ideas on how to have lots of types, each of which represents a subset of a set of enum constants?