Skip to main content

Functional programming with IO

Asking a question

ask :: String -> IO String
ask question = do
putStrLn question
getLine

GHCi> ask "What is your name?"
What is your name?
Andres
"Andres"

Asking many questions

askMany :: [String] -> IO [String]
askMany [] = return []
askMany (q : qs) = do
answer <- ask q
answers <- askMany qs
return (answer : answers)

The standard design pattern on lists is back!

Feels like a map

A map has the wrong result type:

askMany' :: [String] -> [IO String]
askMany' = map ask

But we can sequence a list of plans:

sequence :: [IO a] -> IO [a]
sequence [] = return []
sequence (x : xs) = do
a <- x
as <- sequence xs
return (a : as)

Mapping an IO action

mapM :: (a -> IO b) -> [a] -> IO [b]
mapM f xs = sequence (map f xs)

askMany :: [String] -> IO [String]
askMany questions = mapM ask questions