Yet Another Haskell Tutorial/Io/Solutions
The RealWorld Solution
[edit | edit source]Actions
[edit | edit source]Using if, we get something like:
main = do hSetBuffering stdin LineBuffering putStrLn "Please enter your name:" name <- getLine if name == "Simon" || name == "John" || name == "Phil" then putStrLn "Haskell is great!" else if name == "Koen" then putStrLn "Debugging Haskell is fun!" else putStrLn "I don't know who you are."
Note that we don't need to repeat the dos inside the ifs, since these are only one action commands.
We could also be a bit smarter and use the elem
command which is
built in to the Prelude:
main = do hSetBuffering stdin LineBuffering putStrLn "Please enter your name:" name <- getLine if name `elem` ["Simon", "John", "Phil"] then putStrLn "Haskell is great!" else if name == "Koen" then putStrLn "Debugging Haskell is fun!" else putStrLn "I don't know who you are."
Of course, we needn't put all the putStrLn
s inside the if
statements. We could instead write:
main = do hSetBuffering stdin LineBuffering putStrLn "Please enter your name:" name <- getLine putStrLn (if name `elem` ["Simon", "John", "Phil"] then "Haskell is great!" else if name == "Koen" then "Debugging Haskell is fun!" else "I don't know who you are.")
Using case, we get something like:
main = do hSetBuffering stdin LineBuffering putStrLn "Please enter your name:" name <- getLine case name of "Simon" -> putStrLn "Haskell is great!" "John" -> putStrLn "Haskell is great!" "Phil" -> putStrLn "Haskell is great!" "Koen" -> putStrLn "Debugging Haskell is fun!" _ -> putStrLn "I don't know who you are."
Which, in this case, is actually not much cleaner.
The IO Library
[edit | edit source]A File Reading Program
[edit | edit source]The code might look something like:
module DoFile where import IO main = do hSetBuffering stdin LineBuffering putStrLn "Do you want to [read] a file, ...?" cmd <- getLine case cmd of "quit" -> do putStrLn ("Goodbye!") return () "read" -> do doRead; main "write" -> do doWrite; main _ -> do putStrLn ("I don't understand the command " ++ cmd ++ ".") main doRead = do putStrLn "Enter a file name to read:" fn <- getLine bracket (openFile fn ReadMode) hClose (\h -> do txt <- hGetContents h putStrLn txt) doWrite = do putStrLn "Enter a file name to write:" fn <- getLine bracket (openFile fn WriteMode) hClose (\h -> do putStrLn "Enter text (dot on a line by itself to end):" writeLoop h) writeLoop h = do l <- getLine if l == "." then return () else do hPutStrLn h l writeLoop h
The only interesting things here are the calls to bracket
, which
ensure the that the program lives on, regardless of whether there's a
failure or not; and the writeLoop
function. Note that we need to
pass the handle returned by openFile
(through bracket
to
this function, so it knows where to write the input to).
Alternatively, we can make a version with readFile
and writeFile
that doesn't use bracket
:
doRead = do putStrLn "Enter a file name to read:" fn <- getLine txt <- readFile fn putStr txt doWrite = do putStrLn "Enter a file name to write:" fn <- getLine txt <- getWriteLines writeFile fn txt getWriteLines = do l <- getLine if l == "." then return "" else do lines <- getWriteLines return (line++"\n"++lines)