For in Haskell

Haskell provides several ways to implement loops and iterations. Here are some basic types of loops in Haskell.

import Control.Monad (forM_, when)

main :: IO ()
main = do
    -- The most basic type, with a single condition.
    let loop1 i
          | i <= 3 = do
              print i
              loop1 (i + 1)
          | otherwise = return ()
    loop1 1

    -- A classic initial/condition/after loop.
    forM_ [0..2] print

    -- Another way of accomplishing the basic "do this N times" iteration.
    forM_ [0..2] $ \i -> putStrLn $ "range " ++ show i

    -- Infinite loop that breaks.
    let loop2 = do
          putStrLn "loop"
          return ()  -- In Haskell, we use 'return ()' instead of 'break'
    loop2

    -- Demonstrating 'continue' behavior.
    forM_ [0..5] $ \n -> when (odd n) $ print n

In Haskell, we don’t have explicit for loops like in imperative languages. Instead, we use recursion, list comprehensions, and higher-order functions to achieve similar results.

  1. The first loop is implemented using recursion. We define a function loop1 that calls itself with an incremented value until the condition is met.

  2. The second loop uses forM_ from the Control.Monad module. It’s similar to a traditional for loop, iterating over a list of values.

  3. The third example also uses forM_, but we’re using a lambda function to print a string along with each value.

  4. In Haskell, there’s no direct equivalent to an infinite loop with a break. Instead, we define a function that could potentially loop forever, but in this case, it just executes once.

  5. The last example demonstrates how to skip iterations (similar to continue). We use when from Control.Monad to only execute the print function when the number is odd.

Here’s the output when you run this program:

$ runhaskell for.hs
1
2
3
0
1
2
range 0
range 1
range 2
loop
1
3
5

In Haskell, we often use list comprehensions, map, filter, and fold functions to process data, which can replace many use cases of traditional loops. We’ll see more of these patterns when we look at list processing and other data structures.