Channel Directions in Haskell

In Haskell, we can implement channel-like behavior using the Control.Concurrent.Chan module. While Haskell doesn’t have built-in channel direction specifications like Go, we can achieve similar functionality using type signatures.

First, let’s import the necessary modules:

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

Now, let’s define our ping and pong functions:

-- This `ping` function only writes to the channel.
ping :: Chan String -> String -> IO ()
ping chan msg = writeChan chan msg

-- The `pong` function reads from one channel and writes to another.
pong :: Chan String -> Chan String -> IO ()
pong chanIn chanOut = do
    msg <- readChan chanIn
    writeChan chanOut msg

In the ping function, we only write to the channel. The type signature Chan String -> String -> IO () ensures that we can only write to the channel.

The pong function reads from one channel and writes to another. Its type signature Chan String -> Chan String -> IO () doesn’t explicitly prevent reading from the output channel or writing to the input channel, but we can follow the convention in our implementation.

Now, let’s implement the main function:

main :: IO ()
main = do
    pings <- newChan
    pongs <- newChan
    
    ping pings "passed message"
    pong pings pongs
    
    result <- readChan pongs
    putStrLn result

In the main function, we create two channels using newChan. We then call ping and pong functions, and finally read and print the result from the pongs channel.

To run this program, save it as ChannelDirections.hs and use the following command:

$ runhaskell ChannelDirections.hs
passed message

In this Haskell version, we’ve used Chan from Control.Concurrent.Chan to mimic Go’s channels. While Haskell doesn’t have built-in channel direction specifications, we can achieve similar behavior through careful use of type signatures and adhering to conventions in our implementation.

Haskell’s type system and its support for concurrent programming through the Control.Concurrent module allow us to create robust and type-safe concurrent programs, similar to Go’s approach with channel directions.