我主要对Either
monad 和它的所有 uilitites 感兴趣Control.Error
。阅读errors-1.0:简化的错误处理,我确信应该将纯错误与IO 错误分开。这意味着error
,fail
是exitFailure
应简化为 IO monad 的函数。纯计算可以并且将会产生条件错误,但是是确定性的。
目前,在使用folds时,我遇到了一种情况,数组中的元素可能会产生条件错误,从而使整个计算无法满足。例如(使用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
情况是:我正在使用具有复杂类型的 acc,只是因为如果没有找到单个元素进行替换,那么整个值是不可计算的。
我的问题是:这丑吗?有没有更好的方法来做到这一点?由于一些 IO 检查,EitherT CPError IO String
我有一些更糟糕的实用程序类型。acc