Channel Synchronization in PureScript

Our example demonstrates how to use channels for synchronization across concurrent operations. In PureScript, we’ll use the Aff monad for asynchronous effects and Channel from the purescript-channels library for communication between concurrent processes.

First, let’s import the necessary modules:

module Main where

import Prelude

import Effect (Effect)
import Effect.Aff (Aff, launchAff_, delay)
import Effect.Class.Console (log)
import Data.Time.Duration (Milliseconds(..))
import Control.Coroutine (Process, await, emit)
import Control.Coroutine.Aff (produce, consume)

Now, let’s define our worker function. This function will simulate some work and then signal completion:

worker :: Process Aff Unit Boolean
worker = do
  log "working..."
  delay (Milliseconds 1000.0)
  log "done"
  emit true

In our main function, we’ll set up the producer-consumer pattern to mimic the channel synchronization:

main :: Effect Unit
main = launchAff_ do
  let producer = produce worker
  consume producer \done -> do
    log "Received completion signal"

To run this program:

$ spago run
working...
done
Received completion signal

In this PureScript version, we use the Aff monad to handle asynchronous operations. The worker function is defined as a Process that emits a boolean value when it’s done.

The produce function creates a producer from our worker process, and consume waits for the produced value, effectively synchronizing the main thread with the completion of the worker.

If you removed the consume line from this program, it would exit before the worker even started, similar to the original example.

This approach demonstrates how to achieve similar synchronization patterns in PureScript, even though the language doesn’t have built-in concepts like goroutines or channels. Instead, we leverage the Aff monad and the purescript-coroutines library to manage concurrency and communication between processes.