Search code examples
haskellerror-handlingcommand-line-interfaceuser-experience

How should a Haskell command line script report errors from `read`?


I'm uncertain about the correct way to report errors from read creating an instance in response to user input at the command line within a main = do ....

Specifically, I have a constructor that validates its arguments and reports an error in the usual way

-- ...
Right cfg  -> cfg
Left err -> error (show err)

and an implementation of read that uses this constructor. However inside my implementation I have a cryptic note (inherited from some long-ago research that I've since lost track of) that removes error information

instance Read ... where
        readsPrec _ i = case ...
            Right cfg  -> [(cfg, "")]
            Left _ -> [] -- Loses error information, but conforms to specification of 'readsPrec' in 'Read'

so that my command line parser

main :: IO ()
main = do
    ... read

reports all errors generated by the constructor as merely

Prelude.read: no parse

If I ignore my cryptic comment and instead have

Left err -> error (show err)

in the constructor, then I get complete error information reported to the user:

script: Detailed error information here
  CallStack (from HasCallStack):
  error, called at ./Pkg/Module.hs:371:57 in main:Pkg.Module

(though with stack and line information I'd rather not report in this context).

So I have three related questions about this:

  1. Is there actually any reason not to report full error information from read using Left err -> error (show err)?
  2. If so and something like Left err -> [] is required there, how do I report read or constructor errors at the command line?

and (not as important)

  1. How do i get rid of the line an stack information when reporting from read in my main = do ...?

Solution

    1. Yes: pure code cannot catch error calls. It is frequently useful to know from pure code that read (well, reads) has failed.
    2. Use a different class than Read for parsing that lets you report errors more clearly. Each of the popular parser-combinator libraries have facilities for good error reporting.
    3. Use the imaginatively-named errorWithoutStackTrace.