Channels in PureScript

PureScript, like other functional programming languages, doesn’t have built-in channels or goroutines. However, we can simulate similar behavior using the Aff monad for asynchronous effects and Channel from the purescript-channels library. Here’s an equivalent implementation:

module Main where

import Prelude

import Effect (Effect)
import Effect.Console (log)
import Effect.Aff (launchAff_)
import Control.Coroutine (emit)
import Control.Coroutine.Aff (produce)
import Control.Coroutine.Aff as CR

main :: Effect Unit
main = launchAff_ do
  -- Create a new channel
  messages <- CR.channel

  -- Send a value into the channel
  void $ CR.spawn $ produce \emitter -> do
    emit emitter "ping"

  -- Receive a value from the channel
  msg <- CR.recv messages
  log msg

In this PureScript example:

  1. We use the Aff monad to handle asynchronous operations, which is similar to goroutines in concept.

  2. Instead of make(chan string), we use CR.channel to create a new channel.

  3. The go func() anonymous function is replaced with CR.spawn $ produce, which creates a new fiber (similar to a lightweight thread) and sends a value to the channel.

  4. Instead of <-channel syntax for receiving, we use CR.recv to receive a value from the channel.

  5. fmt.Println is replaced with log for console output.

To run this program, you would need to have PureScript and its dependencies installed. Then you can compile and run it using:

$ spago run
ping

By default, sends and receives in PureScript channels also block until both the sender and receiver are ready. This property allows us to wait at the end of our program for the “ping” message without having to use any other synchronization.

Note that while this example demonstrates a similar concept to channels in Go, PureScript’s approach to concurrency and parallelism is generally more functional and based on monads and effects systems. The Aff monad and Channel type provide powerful tools for managing asynchronous operations in a pure functional way.