Reputation: 5410
I have a situation in which the majority of the operations I am using are partial functions. I want the return type of the functions to vary depending on the context, which should determine the kind of exception handling that occurs, and the type of errors that are reported. My current solution is to define a function parameterised by an error type, then implement the operation as an open function using type classes. For example, the following is an implementation of head, assuming a suitable implementation of Error and MonadError for Maybe in terms of the unit type:
class (Error e, MonadError e m) => Head m e | m -> e where
head :: [a] -> m a
errorHead :: (Error e, MonadError e m) => e -> [a] -> m a
errorHead e [] = throwError e
errorHead e (x : xs) = return x
instance Head Maybe () where
head = errorHead ()
instance Head (Either String) String where
head = errorHead "error: empty list"
The advantage of this implementation is that different errors can be thrown depending on the context in which head is called. The question I have is whether this can be accomplished without defining the function using an auxiliary operation and open functions. If not, the second question is whether this solution is optimal. In particular, is there a better way to achieve this behavior?
Upvotes: 4
Views: 113
Reputation: 11251
The http://hackage.haskell.org/package/errors package has many utilities for moving between Maybe
, Either
, MaybeT
, and EitherT
.
Upvotes: 2