Proposal: Add readMaybe (and possibly readEither) to Prelude, make Haddocks for read more cautionary

Ivan Lazar Miljenovic ivan.miljenovic at gmail.com
Wed Dec 28 04:56:57 UTC 2016


On 28 December 2016 at 15:46, David Feuer <david.feuer at gmail.com> wrote:
> On Dec 27, 2016 10:59 PM, "Simon Jakobi via Libraries"
> <libraries at haskell.org> 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 at gmail.com
http://IvanMiljenovic.wordpress.com


More information about the Libraries mailing list