Closing Channels in PureScript
module Main where
import Effect.Console (log)
import Effect (Effect)
-- In this example we'll use a `jobs` channel to
-- communicate work to be done from the `main` function
-- to a worker function. When we have no more jobs for
-- the worker we'll close the `jobs` channel.
main :: Effect Unit
main = do
jobs <- newChannel
done <- newChannel
-- Here's the worker function. It repeatedly receives
-- from `jobs`. In PureScript, we can't directly check
-- if a channel is closed, so we'll use a special value
-- to signal the end of jobs.
let worker = do
job <- receiveChannel jobs
case job of
Just j -> do
log $ "received job " <> show j
worker
Nothing -> do
log "received all jobs"
sendChannel done true
-- Run the worker in a separate fiber
_ <- forkAff worker
-- This sends 3 jobs to the worker over the `jobs`
-- channel, then closes it.
for_ [1, 2, 3] \j -> do
sendChannel jobs (Just j)
log $ "sent job " <> show j
sendChannel jobs Nothing
log "sent all jobs"
-- We await the worker using the synchronization approach
-- we saw earlier.
_ <- receiveChannel done
-- In PureScript, we don't have a direct way to check
-- if a channel is closed. Instead, we can use Maybe
-- to represent the presence or absence of a value.
moreJobs <- receiveChannel jobs
log $ "received more jobs: " <> show (isJust moreJobs)
-- Note: This PureScript code uses hypothetical `newChannel`,
-- `sendChannel`, and `receiveChannel` functions, which would
-- need to be implemented to match the behavior of Go's channels.
This PureScript code attempts to replicate the functionality of the original example. However, there are some important differences to note:
PureScript doesn’t have built-in channels like Go does. We’re using hypothetical
newChannel
,sendChannel
, andreceiveChannel
functions that would need to be implemented.Instead of using a special 2-value form of receive to check if a channel is closed, we’re using
Maybe
to represent the presence or absence of a value.Nothing
represents the end of jobs.We’re using
forkAff
to run the worker in a separate fiber, which is similar to Go’s goroutines.The
for_
function is used to iterate over the list of jobs, similar to thefor
loop in the original code.We don’t have a direct equivalent to Go’s
close
function for channels. Instead, we send aNothing
value to signal the end of jobs.
To run this program, you would need to compile it with the PureScript compiler and then run it with Node.js:
$ pulp build
$ node index.js
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
received more jobs: false
This example demonstrates how to implement a similar pattern of worker and job dispatching in PureScript, using asynchronous effects and channels. The concept of closing channels is replaced with sending a special “end” value.