doThings1 :: IO () doThings1 = do putStrLn "Doing thing A." putStrLn "Doing thing B." doThings2 :: IO () doThings2 = do _ <- putStrLn "Doing thing A." _ <- putStrLn "Doing thing B." pure () doThings3 :: IO () doThings3 = putStrLn "Doing thing A." >>= (\_ -> putStrLn "Doing thing B.") >>= (\_ -> pure ()) listOfUserIds :: [Int] listOfUserIds = [1, 2, 3] lookupUser :: Int -> IO String lookupUser userId = pure ("User" ++ show userId) usernames :: [IO String] usernames = fmap lookupUser listOfUserIds printOutUsernames :: IO () printOutUsernames = do names <- sequence usernames print names printOutUsernamesAgain :: IO () printOutUsernamesAgain = do names <- traverse lookupUser listOfUserIds print names listOfListOfNumbers :: [[Int]] listOfListOfNumbers = [[1, 2], [3, 4]] sequenceAListOfLists :: IO () sequenceAListOfLists = print (sequence listOfListOfNumbers) main :: IO () main = do doThings1 doThings2 doThings3 printOutUsernames printOutUsernamesAgain sequenceAListOfLists