Non Blocking Channel Operations in PureScript
Here’s the PureScript translation of the non-blocking channel operations example:
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
import Control.Monad.Rec.Class (forever)
import Effect.Aff (Aff, launchAff_, makeAff, nonCanceler)
import Effect.Aff.AVar (AVar)
import Effect.Aff.AVar as AVar
main :: Effect Unit
main = launchAff_ do
messages <- AVar.empty
signals <- AVar.empty
-- Here's a non-blocking receive. If a value is
-- available on `messages` then it will be taken.
-- If not, it will immediately take the default case.
tryReceive messages "no message received"
-- A non-blocking send works similarly. Here `msg`
-- cannot be sent to the `messages` channel, because
-- the channel has no buffer and there is no receiver.
-- Therefore the default case is selected.
let msg = "hi"
trySend messages msg "no message sent"
-- We can use multiple cases to implement a multi-way
-- non-blocking select. Here we attempt non-blocking
-- receives on both `messages` and `signals`.
tryMultiReceive messages signals "no activity"
tryReceive :: AVar String -> String -> Aff Unit
tryReceive avar defaultMsg = do
result <- AVar.tryTake avar
case result of
Just msg -> log $ "received message " <> msg
Nothing -> log defaultMsg
trySend :: AVar String -> String -> String -> Aff Unit
trySend avar msg defaultMsg = do
result <- AVar.tryPut msg avar
if result
then log $ "sent message " <> msg
else log defaultMsg
tryMultiReceive :: AVar String -> AVar Boolean -> String -> Aff Unit
tryMultiReceive messages signals defaultMsg = do
result <- makeAff \cb -> do
void $ AVar.tryTake messages >>= case _ of
Just msg -> cb (Right (Left msg))
Nothing -> pure unit
void $ AVar.tryTake signals >>= case _ of
Just sig -> cb (Right (Right sig))
Nothing -> pure unit
cb (Right (Left defaultMsg))
pure nonCanceler
case result of
Left msg -> log $ "received message " <> msg
Right sig -> log $ "received signal " <> show sigIn this PureScript translation, we use AVar (asynchronous variables) from the purescript-aff library to simulate channels. The tryTake and tryPut functions on AVar provide non-blocking operations similar to the select statements in the original example.
The tryReceive, trySend, and tryMultiReceive functions implement the non-blocking channel operations. They use pattern matching and the Maybe type to handle the presence or absence of values, similar to the select statements in the original code.
Note that PureScript doesn’t have built-in channels or a direct equivalent to Go’s select statement. The makeAff function is used in tryMultiReceive to create a custom asynchronous effect that attempts to receive from multiple AVars, mimicking the multi-way select in the original code.
To run this program, you would need to set up a PureScript project with the necessary dependencies (purescript-aff, purescript-avar, etc.) and then use the PureScript compiler and runtime.
The output of this program would be similar to the original:
no message received
no message sent
no activityThis example demonstrates how to implement non-blocking operations and multi-way selects in PureScript, even though the language doesn’t have built-in channels like Go.