I'm mainly interested in the Either
monad and all it's uilitites from Control.Error
. Reading errors-1.0: Simplified error handling, I got convinced pure errors should be kept apart from IO errors. This means error
, fail
, exitFailure
are functions whose use should be reduced to the IO monad. Pure computations can and will create condition errors, but are deterministic.
Currently, working with folds, I got a situation an element in an array may generate a condition error which makes the whole computation unsatisfiable. For example (using Data.ConfigFile):
type CPError = (CPErrorData, String)
data CPErrorData = ParseError String | ...
type SectionSpec = String
type OptionSpec = String
instance Error CPError
instance Error e => MonadError e (Either e)
get :: MonadError CPError m => ConfigParser -> SectionSpec -> OptionSpec -> m a
dereference :: ConfigParser -> String -> Either CPError String
dereference cp v = foldr replacer v ["executable", "args", "title"]
where
replacer :: String -> Either CPError String -> Either CPError String
replacer string acc = do
res <- acc
value <- get cp "DEFAULT" string
return $ replace ("${" ++ string ++ "}") value res
The situation is: I'm using an acc which has a complex type, just because if a single element isn't found doing the replacement, then the whole value isn't calculable.
My question is: Is this ugly? Is there a better way of doing this? I have some nastier utilities of type EitherT CPError IO String
in the acc
because of some IO checks.