私は主にEitherモナドに興味があり、Control.Error. errors-1.0: Simplified error handling を読んで、純粋なエラーはIO エラーとは別にしておくべきだと確信しました。これはerror、fail、 、exitFailureが、その使用を IO モナドに減らすべき関数であることを意味します。純粋な計算では条件エラーが発生する可能性がありますが、決定論的です。
現在、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