Read
Read
is the class of all types that can be read, that is, parsed. Given a
string representation of a value of such a type, read
will convert this string
representation into the corresponding value. For example,
>>> read "5" :: Int
5
Here, we have to specify the type we expect the return value of read
to have
because GHCi doesn't have enough context to infer the type. We could also parse
the same string as a Double
:
>>> read "5" :: Double
5.0
If we use read
in an expression or function definition where the compiler
can infer the expected return type from the context, we do not need to specify
the return type. For example,
>>> 1.0 / read "5"
0.2
For the Read
class, I won't even list the class definition. This class is
built to support more than simple conversion from strings to values. It is
possible to use the functions supported by types that are instances of Read
to
build simple parsers for expressions over these types. This is clearly more
complex than simple conversion from strings to values, and the methods of the
Read
class reflect this added complexity. The good news is that every type
that is an instance of Read
also supports a function read
to convert a
string to a value of this type:
>>> :info read
read :: Read a => String -> a -- Defined in ‘Text.Read’
Note, however, that read
isn't a great choice to parse text that may be
malformatted. When you try to do this, read
throws an error:
>>> read "5.0" :: Int
*** Exception: Prelude.read: no parse
Here, the string "5.0" represents a floating point number, but we asked it to
parse it as an Int
. That's not possible, so read
throws an exception.
If you do want to parse an expression that may be malformed, it is better to use
reads
:
>>> reads "5.0" :: [(Int,String)]
[]
>>> reads "5.0" :: [(Float,String)]
[(5.0,"")]
>>> reads "5.0a" :: [(Float,String)]
[(5.0,"a")]
reads
returns a list of pairs. For every valid parse, the list contains a pair
consisting of the parsed value and a string containing the characters not
consumed during parsing. In the first example, we ask for a list of type
[(Int,String)]
, which means that we try to parse "5.0" as an integer. Since
there is no valid parse of this as an integer, the result is the empty list. in
the second example, we expect a list of type [(Float,String)]
, that is, we try
to parse "5.0" as a floating point number. Since this is possible, we obtain the
list [(5.0,"")]
. The string is empty in this case because the entire input
"5.0"
is parsed as a floating point number. In the last example, we have the
additional character a
after 5.0
. In this case, reads
parses 5.0
as a
Float
and does not consume the a
. So the result is [(5.0,"a")]
.
For simple types, such as Int
, Bool
, Double
, etc., the list produced by
reads
is always either empty or contains a single pair. The ability to return
multiple possible parses is used only when building simple expression parsers.