I just tried writing
read (show 42)
in ghci. It responds with ‘*** Exception: Prelude.read: no parse’.
My assumption was that it should return 42. My reading of various manuals and tutorials suggests that should happen, as far as I can see. Can anyone explain my error?
3
This is just a quirk of read
and GHCi that frequently trips up new Haskellers, but is the only way it could possibly work if you stop to think about it.
The types of everything are decided at compile time. Even when you’re using GHCi, your input is first analysed to infer and check types and only then run. Nothing that happens at runtime can affect the type checking phase.
read
has type Read a => String -> a
. That type variable a
can be chosen as any type in the Read
typeclass. But the choice has to be made at compile time, and then the choice determines what format it will try to parse out of its input string. There’s no way for it to see that the string is 42
and then decide that it’s parsing an Int
.
(This is quite different from things like Python’s eval
and similar functions in other languages, which do look at the input to decide what type of value they are returning. But in Haskell something with a simple type like Read a => String -> a
can only be parsing a type that can be determined at compile time, without reference to the input data)
In “real” programs written in modules, this isn’t usually a problem, because you will use the value that you get out of read
and generally that will involve passing it to other functions that pin down the type that read
should produce. But in GHCi you “compile” code one line at a time, as it’s entered. So when you compile the call to read
the compiler can’t see your intended future use of the return value, and can’t use them to help infer the type. It has to just guess (using the ExtendedDefaultRules
extension that is on by default in GHCi to avoid an ambiguous type error), and the type it guesses is ()
.
The read
parser for ()
doesn’t accept 42
, and that’s why you get a no parse
exception.
You can address this by either using a type annotation to specify what type you expect read
to parse instead of letting GHCi guess, or by using read
in a context where the compiler can see what you expect to do with the result (assuming that pins down a particular type), or by using ()
instead of 42
as the value you try to round-trip through show
and read
.
The type of read (show 42)
is ambiguous and has been defaulted to ()
. If you give an explicit type signature, you’ll be good to go:
> read (show 42) :: Int
42