After reading the Haskell books I am kind of confused (or I simply forgot) how to get a value from the IO domain, into the 'Haskell world' to parse it, like so:
fGetSeq = do
input <- sequence [getLine, getLine, getLine]
fTest input
mapM_ print input
fTest = map (read :: String -> Int)
Obviously compiler complains. Couldn't match [] with IO
. Is there a simple rule of thumb for passing values between 'worlds' or is it just my bad by omitting typesigs?
get a value from the IO domain, into the 'Haskell world'
You use the bind operator: (>>=) :: Monad m => m a -> (a -> m b) -> m b
.
If m = IO
it looks like: (>>=) :: IO a -> (a -> IO b) -> IO b
.
As you can see, the function with type a -> IO b
addresses the a
without IO
.
So given a value in the IO monad, e.g. getLine :: IO String
:
getInt :: IO Int
getInt = getLine >>= (\s -> return (read s))
Here, s :: String
, read :: String -> Int
, and return :: Int -> IO Int
.
You can rewrite this using a do-block:
getInt :: IO Int
getInt = do
s <- getLine
return (read s)
Or use the standard library function that does exactly this:
getInt :: IO Int
getInt = readLn
As for your example, you can immediately fix it using a let-binding:
foo :: IO ()
foo = do
input <- sequence [getLine, getLine, getLine]
let ints = bar input
mapM_ print ints
bar :: [String] -> [Int]
bar = map read
Or you can restructure it to use getInt
as defined above:
foo :: IO ()
foo = sequence [getInt, getInt, getInt] >>= mapM_ print