Range Over Channels in Haskell

In Haskell, we can use channels to communicate between different parts of our program. Let’s see how we can iterate over values received from a channel.

import Control.Concurrent.Chan
import Control.Monad (forM_)

main :: IO ()
main = do
    -- We'll iterate over 2 values in the `queue` channel.
    queue <- newChan

    -- Write two values to the channel
    writeChan queue "one"
    writeChan queue "two"

    -- This function reads all values from the channel until it's empty
    let drainChan chan = do
            empty <- isEmptyChan chan
            if empty
                then return []
                else do
                    x <- readChan chan
                    xs <- drainChan chan
                    return (x:xs)

    -- Read all values from the channel
    values <- drainChan queue

    -- Iterate over the values and print them
    forM_ values $ \elem ->
        putStrLn elem

To run the program:

$ runhaskell range_over_channels.hs
one
two

In this example, we’re using Haskell’s Chan type to simulate a channel. We write two values to the channel, then read all values from it and print them.

The drainChan function is used to read all values from the channel until it’s empty. This is similar to ranging over a channel in other languages.

Note that Haskell’s Chan doesn’t have a built-in concept of closing, unlike channels in some other languages. In Haskell, we typically signal the end of data in other ways, such as sending a special value or using a separate mechanism to coordinate between producers and consumers.

This example demonstrates how we can work with channel-like constructs in Haskell, even though the exact semantics might differ from channels in other languages.