I'm using getOpt
to parse and validate the args provided by getArgs
.
I chose to use the action based approach for getOpt
, here are the types.
data Options = Options { afield :: foo, bfield :: bar}
type Action = Either String (Options -> Options)
Then I fold over the actions list on a default options record using,
evaluateActions :: Either [String] Options -> Action -> Either [String] Options
evaluateActions (Left errors) (Left err) = Left $ err:errors
evaluateActions (Left errors) (Right _) = Left errors
evaluateActions (Right _) (Left err) = Left [err]
evaluateActions (Right option) (Right action) = Right $ action option
Afterwards I am left with the desired type Either [String] Options
.
Upon error(s), I want to print the strings out and exit with the error code InvalidArgument.
printErrorsThenExit :: [String] -> ExitCode -> IO ()
printErrorsThenExit errs code =
hPutStr stderr (concat errs) >>
exitWith code
I am struggling to glue this together in my main function without writing something like the following which doesn't work with the types:
opts <- case result of
Left errors -> printErrorsThenExit errors illegalArgument
Right options -> return options
I have seen the when
function but I don't think it helps since I need to unwrap the Either.
Anyone know how I can express failure process in Haskell?
CodePudding user response:
Since we have
exitWith :: ExitCode -> IO a
you can simply change your printErrorsThenExit
type to
printErrorsThenExit :: [String] -> ExitCode -> IO a
-- ^ --
The point is: if an IO action does not actually return (but exits the whole program) its type can be IO a
for any a
, claiming that it can fit any type.
Your main
code should then just work as it is.