For loops

The functions for_ and for can be used to perform simple repetitions. They are named after “for loops”, a common feature in most programming languages.

import Data.Foldable (for_)
import Data.Traversable (for)

import Control.Monad (when)

main =
  do

Use the for_ function (from Data.Foldable) to iterate over a list. Here we say “for each number i in the list 1 through 5, print i.”

    putStr "Numbers:"
    for_ [1..5] $ \i ->
      do
        putStr " "
        putStr (show i)
    putStr "\n"

Use the when function (from Control.Monad) to perform an action conditionally. Here we again loop over a list from 1 to 5, but we only print i when it is odd.

    putStr "Odds:"
    for_ [1..5] $ \i ->
        when (odd i) $
          do
            putStr " "
            putStr (show i)
    putStr "\n"

Equivalently, we could use the filter function (in Prelude and in Data.List) to select only the odd list elements, and then loop over the result.

    putStr "Odds:"
    for_ (filter odd [1..5]) $ \i ->
      do
        putStr " "
        putStr (show i)
    putStr "\n"

The loop body can return a value. The for_ function ignores this value, but there is a related function called for (in Data.Traversable) which collects all the return values in a list.

The underscore at the end of the name for_ is a hint that for_ is the result-discarding variant of for. Some other functions follow this naming convention as well.

    tens <-
      for [1..3] $ \i ->
        do
          putStr (show i ++ " ")
          return (i * 10)
    putStr ("(sum: " ++ show (sum tens) ++ ")\n")
$ runhaskell for-loops.hs
Numbers: 1 2 3 4 5
Odds: 1 3 5
Odds: 1 3 5
1 2 3 (sum: 60)