
On 28 December 2016 at 15:46, David Feuer
On Dec 27, 2016 10:59 PM, "Simon Jakobi via Libraries"
wrote: read [1] is an easy way to introduce runtime exceptions into programs, but its documentation doesn't sufficiently warn of this danger. read's safe alternatives, Text.Read.readMaybe [2] and Text.Read.readEither [3], are relatively unknown and too hard to find.
A while back I brought up the idea of adding custom warning "classes", allowing such functions to be tagged partial. I should probably put together a proper proposal now that we have that process. Personally, I'd love to remove read from the Prelude, but that would be hard.
1. Add readMaybe to the Prelude
+1
2. Add readEither to the Prelude
+1
3. Change the documentation for read to point out the partiality and to recommend the above alternatives:
+1
> If there's any uncertainty w.r.t. the shape of the input, readMaybe or readEither should be used instead.
I would put it more strongly:
read should be applied only to strings that are known to have been produced by methods of the Show class.
More so than that: you know that it's for this exact type. (Though I have [ab]used `read` to convert a String value consisting solely of digits to an `Int` within a parsing library.)
Design issues:
I am somewhat doubtful about the benefit of readEither over readMaybe: While readEither does give additional info on the kind of parse failures, that information is encoded in a String error message, from which it must be parsed if it is needed in the program.
It's still the right way to handle error reporting for Read.
Very wrong:
do x <- read <$> getInput use x
Correct, in some contexts, but extremely lousy:
do x <- read <$> getInput evaluate (force x) use x
Correct, but uninformative:
do Just x <- readMaybe <$> getInput use x
Correct and informative:
do ip <- readEither <$> getInput either (throwIO . parseError) use ip (For some value of parseError)
Or, when reasonable,
do ip <- readEither <$> getInput either (\m -> displayMessage m *> tryAgain) ip
I would argue that if you're doing something like this then you should really be using a proper combinator parsing library. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com