Basic Input and Output
Prerequisites: Strings and characters
So far every program has only printed. To read input, you use more IO
actions inside do.
getLine and <-
-- Try it: printf 'Ada\n36\n' | runghc main.hs
main :: IO ()
main = do
putStrLn "What is your name?"
name <- getLine
putStrLn "How old are you?"
ageText <- getLine
let age = read ageText :: Int
putStrLn ("Hello, " ++ name ++ "! Next year you'll be " ++ show (age + 1) ++ ".")
What is your name?
How old are you?
Hello, Ada! Next year you'll be 37.
getLine :: IO Stringis an action that, when run, produces aString. You can't use it as a string directly.name <- getLineruns the action and names its result. Use<-for results of IO actions andletfor ordinary values.- The first comment line shows how to feed input from the shell instead of typing it.
Validating input
read crashes on bad input. Use readMaybe and a recursive action to
ask again:
-- Try it: printf 'abc\n-4\n7\n' | runghc main.hs
import Text.Read (readMaybe)
askNumber :: IO Int
askNumber = do
putStrLn "Enter a positive number:"
input <- getLine
case readMaybe input of
Just n | n > 0 -> return n
_ -> do
putStrLn ("Not a positive number: " ++ input)
askNumber
main :: IO ()
main = do
n <- askNumber
putStrLn ("Its square is " ++ show (n * n))
Enter a positive number:
Not a positive number: abc
Enter a positive number:
Not a positive number: -4
Enter a positive number:
Its square is 49
return nwraps a plain value as an IO action's result. Unlike other languages,returndoesn't exit the function — it just produces the value.Just n | n > 0combines a pattern with a guard.- The loop is recursion:
askNumbercalls itself.
Reading all input with interact
interact passes the whole standard input to a pure function and prints
the string it returns — perfect for filters:
-- Try it: printf 'banana\napple\ncherry\n' | runghc main.hs
import Data.List (sort)
main :: IO ()
main = interact (unlines . sort . lines)
apple
banana
cherry
Command-line arguments
-- illustrative: run as runghc greet.hs Ada Grace
import System.Environment (getArgs, getProgName)
main :: IO ()
main = do
args <- getArgs
name <- getProgName
putStrLn (name ++ " got " ++ show (length args) ++ " arguments")
mapM_ (\a -> putStrLn ("Hello, " ++ a)) args
greet got 2 arguments
Hello, Ada
Hello, Grace
Keep IO at the edges
A good Haskell program has a thin main that reads input, calls pure
functions to do the real work, and prints the result. Pure functions are
easy to test in GHCi and can't be broken by the outside world.