Here’s a program:

main = do

text <- getLine

putStr "Your name is: "

putStrLn text

We can run it like this:

$ ./One

Ben

Your name is: Ben

It’s easy to think of this program as having three steps (and it does) — but the whole program is represented by a single value of type IO () :

> :t main

main :: IO ()

We could use a different expression of type IO () as a main function, instead of this do block. For example, putStrLn “Hello" has the right type and we could just write this:

main = putStrLn "Hello"

Or we could do something complicated-looking like this:

main = snd (head l) l = [(3, a >>= b), undefined, (8, void $ return 7)] a = getLine

b = fst (putStrLn, putStrLn)