Reputation: 55
I have a list of type [Int]
which can only contain two values: 0
or 1
.
Example : [0, 0, 1, 1, 0, 0]
I would like to iterate through this list and when the current element is a 0, print '_'
and if it is a 1 print '*'
.
For the previous list, here is the result on the standard output :
__**__
I think that I have to do something like that :
displayLine :: [Int] -> IO [Int]
displayLine (0 : xs) =
do
print '_'
-- next char
displayLine (1 : xs) =
do
print '*'
-- next char
How can I display a character and continue recursion with the next character?
Upvotes: 3
Views: 247
Reputation: 5678
The nice thing about do
-notation is that the code usually looks just like it would in an imperative language (only better) : a couple of statements and a return
at the end:
displayLine (0 : xs) = do
print '_'
ys <- displayLine xs -- ys will be identical to xs,
return (0:ys)
Don't forget to add a case for displayLine []
, unless all of your lists are infinite....
BTW, do you really need to return
anything, as the list is returned unchanged? If not, the type of displayLine
could be [Int] -> IO ()
and the definition could be even simpler..
Upvotes: 2
Reputation: 476557
You call displayLine
with the tail of the list. But here the type will be IO ()
, not IO [Int]
since the action does not return anything:
displayLine :: [Int] -> IO ()
displayLine (0 : xs) = do
print '_'
displayLine xs
displayLine (1 : xs) = do
print '*'
displayLine xs
You probably also want to use putChar :: Char -> IO ()
to print a single char, since print
will call show
and thus print a Char
literal, and a new line.
This however duplicates logic. We can make use of mapM_ :: (Foldable f, Monad m) => (a -> m b) -> f a -> m ()
to perform a mapping where each element performs a monadic action:
displayLine :: [Int] -> IO ()
displayLine = mapM_ (putChar . f)
where f 0 = '_'
f 1 = '*'
For example:
Prelude> displayLine [0,1,1,0,1,0] >> putStrLn ""
_**_*_
The putStrLn ""
at the end is used to start a new line after the characters have been printed.
Upvotes: 5