7

I'm complete newbie on Haskell. My Haskell script with GHCi,

Prelude> let a = putStrLn getLine

makes an error like this.

<interactive>:1:17:
    Couldn't match expected type `String'
           against inferred type `IO String'
    In the first argument of `putStrLn', namely `getLine'
    In the expression: putStrLn getLine
    In the definition of `a': a = putStrLn getLine
Prelude> 

Why doesn't it work and how can I print something input from stdin?

eonil
  • 83,476
  • 81
  • 317
  • 516

1 Answers1

15
putStrLn :: String -> IO ()
getLine :: IO String

The types do not match. getLine is an IO action, and putStrLn takes a plain string.

What you need to do is bind the line inside the IO monad in order to pass it to putStrLn. The following are equivalent:

a = do line <- getLine
       putStrLn line

a = getLine >>= \line -> putStrLn line

a = getLine >>= putStrLn
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 2
    You've got a value stuck in the IO monad `m a`, and a function that returns its value in the IO monad `a -> m b`. You want to end up with an IO action `m b`. All together that's `m a -> (a -> m b) -> m b`. [Stop. Hoogle time.](http://haskell.org/hoogle/?hoogle=(a+-%3E+m+b)+-%3E+m+a+-%3E+mb) `>>=` is one of the first results. :) – Dan Burton Mar 07 '11 at 07:14
  • Unfortunately there are no results for the exact instantiation we need: `IO String -> (String -> IO ()) -> IO ()`. – luqui Mar 07 '11 at 07:26
  • Eonil it would be closer to the intention of your `putStrLn getLine` to use something like the reversed bind: `putStrLn =<< getLine`. This is `fmap` followed by `join`, so we could write `join (putStrLn <$> getLine)`. I wish there were something lovelier than `(=<<)` – applicative Mar 08 '11 at 01:36