Take the 2-minute tour ×

I was reading up on the deeper workings of the IO monad in Haskell on their wiki and I came across this code

      b <- ask "How old are you?"
      return ()
ask s = do putStr s

Which makes sense to me. The ask function should print out the string given to it and return a line that can be passed into a or b.

However loading this into GHCi I get problems. Tells me there isn't an instance of Read from use of ask and that I could import GHC.Read. That shouldn't be necessary. This code was on Haskell.org so I would think it should work. Was something in the language changed or is there some big piece of understanding that I am missing?

share|improve this question

2 Answers 2

up vote 4 down vote accepted

I've done two changes to the code.

  1. Fix the indentation -- remember that haskell is "space sensitive", so please make sure the code looks properly aligned
  2. Explicit type signatures. This is a bit tricky. But as rule of thumb, when code that you would've expect to work doesn't. Try to annotate your code with types, like shown below. You'll understand why this is so in time.

Here's the modified code:

main = do
  a <- askString "What is your name?"
  b <- askOther "How old are you?"

  putStrLn ""
  putStrLn "Name and age"
  putStrLn (a :: String)
  print (b :: Int)
  return ()

askString s = do
  putStrLn s

askOther s = do
  putStrLn s

Edit: Sorry, the code actually compiles now. Again, as your haskell matures, you'll see why askString and askOther does look different. Here is an example run:

$ runghc Hello.hs
What is your name?
How old are you?

Name and age
share|improve this answer
DOes the difference between askOther and askStringhave to do with their usage as one passes an Int and the other passes a String? –  Ryan Cori Mar 9 '13 at 8:44
@RyanCori, askString :: String -> IO String, but askOther :: (Read a) => String -> IO a (read missingnos excellent answer for how a can become an Int). You could use askOther also for strings, but then the user of the program must enter "Arash" rather than simply Arash. –  Tarrasch Mar 9 '13 at 14:54

If you create a file with just the ask function (without the problematic main) and load it to ghci you will be able to see that ask's type is

ask :: (Read a) => String -> IO a

meaning that it is polymorphic in the return type.

The problem is that when you do

a <- ask "What is your name"

the compiler needs to know what is the type of a so it can use the correct deserializing function for the line you read from the inpout. But a isn't used anywhere else and there are no type signatures anywere either so the type inference can't deduce the type of a. The compiler gives up and gives you that "ambiguos types" message.

There are two main ways to fix that:

  1. Make the ask function always return the same type. You can do this either by adding an specific signature

    ask :: String -> IO String

    Or by changing the readLn into something like getLine.

  2. Add type signatures where you are using the polymorphic functions. You can either add a type signature to the ask call itself:

    a <- ask "What is your name" :: IO String

    or you can add it directly to the variable

    (a :: String) <- ask "What is your name"

    however, this second option isn't allowed by the default Haskell syntax. you need to enable the ScopedTypeVariables extention by adding the following comment as the first line in your file

    {-# LANGUAGE ScopedTypeVariables #-}
share|improve this answer

Your Answer


