Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [73]

By Root 566 0
value to display it on the terminal!

ghci> 3

3

ghci> print 3

3

ghci> map (++"!") ["hey","ho","woo"]

["hey!","ho!","woo!"]

ghci> print $ map (++"!") ["hey","ho","woo"]

["hey!","ho!","woo!"]

When we want to print out strings, we usually use putStrLn because we don’t want the quotes around them. However, for printing out values of other types to the terminal, print is used the most often.

when


The when function is found in Control.Monad (to access it, use import Control.Monad). It’s interesting because in a do block, it looks like a flow-control statement, but it’s actually a normal function.

when takes a Bool and an I/O action, and if that Bool value is True, it returns the same I/O action that we supplied to it. However, if it’s False, it returns the return () action, which doesn’t do anything.

Here’s a small program that asks for some input and prints it back to the terminal, but only if that input is SWORDFISH:

import Control.Monad

main = do

input <- getLine

when (input == "SWORDFISH") $ do

putStrLn input

Without when, we would need to write the program like this:

main = do

input <- getLine

if (input == "SWORDFISH")

then putStrLn input

else return ()

As you can see, the when function is useful when we want to perform some I/O actions when a condition is met, but do nothing otherwise.

sequence


The sequence function takes a list of I/O actions and returns an I/O action that will perform those actions one after the other. The result that this I/O action yields will be a list of the results of all the I/O actions that were performed. For instance, we could do this:

main = do

a <- getLine

b <- getLine

c <- getLine

print [a,b,c]

Or we could do this:

main = do

rs <- sequence [getLine, getLine, getLine]

print rs

The results of both these versions are exactly the same. sequence [getLine, getLine, getLine] makes an I/O action that will perform getLine three times. If we bind that action to a name, the result is a list of all the results. So in this case, the result would be a list of three things that the user entered at the prompt.

A common pattern with sequence is when we map functions like print or putStrLn over lists. Executing map print [1,2,3,4] won’t create an I/O action, but instead will create a list of I/O actions. Effectively, this is the same as writing this:

[print 1, print 2, print 3, print 4]

If we want to transform that list of I/O actions into an I/O action, we must sequence it:

ghci> sequence $ map print [1,2,3,4,5]

1

2

3

4

5

[(),(),(),(),()]

But what’s with the [(),(),(),(),()] at the end of the output? Well, when we evaluate an I/O action in GHCi, that action is performed, and then its result is printed out, unless that result is (). That’s why evaluating putStrLn "hehe" in GHCi just prints out hehe—putStrLn "hehe" yields (). But when we enter getLine in GHCi, the result of that I/O action is printed out, because getLine has a type of IO String.

mapM


Because mapping a function that returns an I/O action over a list and then sequencing it is so common, the utility functions mapM and mapM_ were introduced. mapM takes a function and a list, maps the function over the list, and then sequences it. mapM_ does the same thing, but it throws away the result later. We usually use mapM_ when we don’t care what result our sequenced I/O actions have. Here’s an example of mapM:

ghci> mapM print [1,2,3]

1

2

3

[(),(),()]

But we don’t care about the list of three units at the end, so it’s better to use this form:

ghci> mapM_ print [1,2,3]

1

2

3

forever


The forever function takes an I/O action and returns an I/O action that just repeats the I/O action it got forever. It’s located in Control.Monad. The following little program will indefinitely ask the user for some input and spit it back in all uppercase characters:

import Control.Monad

import Data.Char

main = forever $ do

putStr "Give me some input: "

l <- getLine

putStrLn $ map toUpper l

forM


forM (located in Control.Monad) is like mapM, but its parameters are switched around. The

Return Main Page Previous Page Next Page

®Online Book Reader