Learn and Discover Open Source with Daily Genuine Experience. From Coding, Front End, Back End, Database, and Static Site Generator.
13

## Loop in Haskell With Map, Part One

Table of Content

### Goal of Part One

Process Array Loop by Iterating on List

This is the basic of loop using iteration, with simple array like data structure, the list.

### Example of Doing Loop in Haskell With Map

This tutorial/ guidance/ article is one of three parts. These three combined is going to be a long article. So I won’t speak too much. More on codes, than just words.

The first two parts discuss the most common loop, array in part one and hash in part two. Considering that combining map with function is tricky, This deserve this an article of its own in part three. Part three also contains comparation with other Languages, using Real World Function.

### Defining List

Haskell has a few Array implementation. One that is very common is List. It is actually a linked list that behaves like an Array.

Let’s consider a list construct, contain sequence number from 1 to 9.

``````list :: [Int]
list = [1..9]``````

It is not mandatory to write function declaration. Sometime I put function declaration, just for clarity reason, Also for my personal exercise. It won’t harm anyone. Now we can omit any function declaration for this list.

``list = [1..9]``

### Printing List

``````list = [1..9]

main = do
print list
putStrLn ""``````

This will show:

``[1,2,3,4,5,6,7,8,9]``

We can ignore `do` clause. `do` is just a special syntax for sequencing monad. The type of `main`main is `IO ()`. IO is a monad, hence omitting do.

Relax, forget about Monad, and just go on. Omitting `do` notatin is useful when creating oneliner example. Consider this example of the same code rewritten without do clause. But using `then >>` operator.

`print` is just `putStrLn \$ show`. And `\$` is just an operator to avoid closing bracket. Now we can decompose it as below.

``main = putStrLn (show [1..9]) >> putStrLn ""``

Or using reverse application operator `&`.

``````import Data.Function
main = show [1..9] & putStrLn >> putStrLn ""``````

### List Variation

Let’s add other element to this list.

``````list :: [Int]
list = [1..9] ++ [0]

main = do
putStr "list    : "
putStrLn \$ show list``````

Run this code, and this list will be interpreted as output below.

``list    : [1,2,3,4,5,6,7,8,9,0]``

### Accessing Index

Operator `||` can be used to accessing element by index.

``````main = do
print (list !! 3)``````

This will show 4, because it is a zero based index:

``4``

Since list is actually a linked list, it does not rely on indices. For convenience for coder come from other language, zero based indices can be done this way below.

``````list :: [Int]
list = [1..9] ++ [0]

indices' :: [Int] -> [Int]
indices' l = [0 .. (length l) - 1]

main = do
putStr "list    : "
print list
putStr "indices : "
putStrLn \$ show \$ indices' list
putStrLn ""``````

Do not worry about the dollar `\$` operator. It is just a Haskell operator to avoid paranthese. It could be written as `putStrLn(show(indices’(list)))`

Note that I intentionally using, apostrophe `indices’` punctuation mark, to differ from `indices` in `Control.Lens` library.

This will display:

``````list    : [1,2,3,4,5,6,7,8,9,0]
indices : [0,1,2,3,4,5,6,7,8,9]``````

### Iterate with mapM_

Looping over array in Haskell is this simple. `mapM_` discard newly produced list, and use side effect only, in this case print using IO.

``````main = do
mapM_ print list``````

Wait….!!! This simple !!…. Yes! I also thought it was harder, but it turn out to be very short. This will map each element, and applied it to print function. Let’s see the output

``````1
2
3
4
5
6
7
8
9
0``````

### Iterate with Map

If you care about tor produce new list, `map` is for you.

``````main = do
print \$ map show list``````

This show will convert each element to string, and boxed it into new list of string.

``["1","2","3","4","5","6","7","8","9","0"]``

If you come from other language, and too confused about Haskell notation, you may consider this perspective: `map(callback_function, array)`.

`map` is very useful for transforming one list to another list. However we still need `mapM` or `forM` whenever we need side effect such as display each element using IO.

``````main = do
mapM_ putStrLn (map show list)
putStrLn ""``````

`forM` is just like a `mapM`, with reverse aguments. It is available in `Data.Foldable`.

``````main = do
forM_ (map show list) putStrLn
putStrLn ""``````

Both codes have output as shown below. They are using side effect of newly produced `(map show list)`.

``````1
2
3
4
5
6
7
8
9
0``````

While doing `mapM` or `forM` after `map`seems redundant. It is just an example required in this tutorial, not everything have to be printed out.

### Chaining Function

If you wish for another challenge you can make a complex one liner.

``main = mapM_ (putStr . (": " ++) . show) ([1..9] ++ [0]) >> putStrLn ""``

Or using reverse argument `forM_` to make it looks like regular loop. With the same result.

``main = forM_ ([1..9] ++ [0]) (putStr . (": " ++) . show) >> putStrLn ""``

This will show.

``: 1: 2: 3: 4: 5: 6: 7: 8: 9: 0``

How does it works ? What is this `.` in `(putStr . (”: “ ++) . show)` anyway.

As our need grow, you might desire to use more than one function. The issue is `mapM_` only accept one function. The solution is to chain functions with the dot `.` infix operator. This will accept the sequence of function as a whole compound operation.

### Alternative Loop Form

We can rewrite above loop, even better using `map`. Also with the same result.

``main = putStrLn \$ concat  \$ map ((": " ++) . show) ([1..9] ++ [0])``

Or `concatMap`. Still with the same result.

``main = putStrLn \$ concatMap ((": " ++) . show) ([1..9] ++ [0])``

### Building Block

If you do not like oneliner, you can decompose this complex line using let clause in do block, or where clause in function.

``````main = do
let
myFunctionComposition = (putStr . (": " ++) . show)
myList = ([1..9] ++ [0])
in mapM_ myFunctionComposition myList

putStrLn "" ``````
``````putList :: [Int] -> IO ()
putList myList =
mapM_ myFunctionComposition myList
where
myFunctionComposition = (putStr . (": " ++) . show)

main = do
putList ([1..9] ++ [0])
putStrLn ""  ``````

This will produce exactly the same result.

``: 1: 2: 3: 4: 5: 6: 7: 8: 9: 0``

### View Source File:

In “Part Two” we will discuss about Hash (dictionary).

Happy Coding.