0

I am trying to use the reads function from Prelude, and doctest to test it. Just loading GHCI and typing reads "57x" or Prelude.reads "57x" yields only an empty list [], so I thought I had to import the function myself. According to the docs, it should return a tuple. But running Doctest and in GHCI, I get the error *** Exception: Prelude.read: no parse when putting in any test that has characters in addition to the Integer, ie 54x. What do I need to change to get it to return the proper tuple, as mentioned here, but with INTs instead of DOUBLEs?

I have a haskell file that looks like this:

module StackOverflow where
import Prelude hiding (words, reads)

reads :: String -> [(Int, String)]
-- ^ Takes a string, like "57" and reads the corresponding integer value
--   out of it. It returns an empty list if there is a failure, or a list
--   containing one tuple, with the integer value as the first element of
--   the tuple and a (possibly empty) string of remaining unconvertable extra
--   characters as the second element.
--
--   Examples:
--
--   >>> reads "57"
--   [(57,"")]
--
--   >>> reads "57x"
--   [(57,"x")]
--
reads s = [(read s :: Int,"")]
9
  • 1
    Do you want to use the builtin reads or define your own? Commented Sep 28, 2014 at 21:26
  • I was trying to use my own and override Preludes given the predefined one wasn't working in the GHCI interpreter. Commented Sep 28, 2014 at 21:49
  • What was it doing when you tried to use the Prelude one? Are you only trying to write a new one because the Prelude one didn't seem to work? Commented Sep 28, 2014 at 22:00
  • Correct. If I just have the following in a file module Test where import Prelude with or without the import Prelude, typing reads "54x" or Prelude.reads "54x" with or without the x, I still just get an empty list []. This is why I added the function myself, and had problems with words as noted in my SO question here Commented Sep 28, 2014 at 22:13
  • 3
    That is due to something called type defaulting. Because of reads polymorphic signature, you need to provide a type signature so it knows what type you are expecting. Try reads "54x" :: [(Int, String)]. I believe it defaults to the type [((), String)] if there is no type signature, and [] would be the correct result in that case. Commented Sep 28, 2014 at 22:15

1 Answer 1

1

The reason that you are getting a "no parse" exception is that the type is defaulting to something other than Int (in this case, ()). So, effectively, the expression reads "54x" is being evaluated at the type [((), String)]. This is because in order to select the appropriate Read instance, the type must be fully specified at compile time but this isn't possible because it doesn't know what the String is expected to contain.

You can tell it what type you are expecting from the String by providing an explicit type signature, like this

reads "54x" :: [(Int, String)]

All expressions can be given an explicit type signature and, in fact, sometimes it is necessary in order to avoid an ambiguous type.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.