<div dir="auto"><div><div class="gmail_extra"><div class="gmail_quote">On Dec 27, 2016 10:59 PM, "Simon Jakobi via Libraries" <<a href="mailto:libraries@haskell.org">libraries@haskell.org</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">read [1] is an easy way to introduce runtime exceptions into programs,<br>
but its documentation doesn't sufficiently warn of this danger. read's<br>
safe alternatives, Text.Read.readMaybe [2] and Text.Read.readEither<br>
[3], are relatively unknown and too hard to find.<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
1. Add readMaybe to the Prelude<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"></blockquote></div></div></div><div dir="auto">+1</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
2. Add readEither to the Prelude<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">+1</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
3. Change the documentation for read to point out the partiality and<br>
to recommend the above alternatives:<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">+1 </div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> If there's<br>
any uncertainty w.r.t. the shape of the input, readMaybe or readEither<br>
should be used instead.<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">I would put it more strongly:</div><div dir="auto"><br></div><div dir="auto">read should be applied only to strings that are known to have been produced by methods of the Show class.</div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<br>
Design issues:<br>
<br>
I am somewhat doubtful about the benefit of readEither over readMaybe:<br>
While readEither does give additional info on the kind of parse<br>
failures, that information is encoded in a String error message, from<br>
which it must be parsed if it is needed in the program.</blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">It's still the right way to handle error reporting for Read.</div><div dir="auto"><br></div><div dir="auto">Very wrong:</div><div dir="auto"><br></div><div dir="auto">do</div><div dir="auto"> x <- read <$> getInput</div><div dir="auto"> use x</div><div dir="auto"><br></div><div dir="auto">Correct, in some contexts, but extremely lousy:</div><div dir="auto"><br></div><div dir="auto">do</div><div dir="auto"> x <- read <$> getInput</div><div dir="auto"> evaluate (force x)</div><div dir="auto"> use x</div><div dir="auto"><br></div><div dir="auto">Correct, but uninformative:</div><div dir="auto"><br></div><div dir="auto">do</div><div dir="auto"> Just x <- readMaybe <$> getInput</div><div dir="auto"> use x</div><div dir="auto"><br></div><div dir="auto">Correct and informative:</div><div dir="auto"><br></div><div dir="auto">do</div><div dir="auto"> ip <- readEither <$> getInput</div><div dir="auto"> either (throwIO . parseError) use ip</div><div dir="auto">(For some value of parseError)</div><div dir="auto"><br></div><div dir="auto">Or, when reasonable,</div><div dir="auto"><br></div><div dir="auto">do</div><div dir="auto"> ip <- readEither <$> getInput</div><div dir="auto"> either (\m -> displayMessage m *> tryAgain) ip</div><div dir="auto"></div></div>