Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursive function that prints something

Tags:

haskell

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?

like image 450
Midway Avatar asked Jul 02 '26 11:07

Midway


2 Answers

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.

like image 104
Willem Van Onsem Avatar answered Jul 04 '26 04:07

Willem Van Onsem


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..

like image 35
Hans Lub Avatar answered Jul 04 '26 04:07

Hans Lub



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!