Select in PureScript

Our example demonstrates how to use channels and concurrency in PureScript. We’ll create two channels and select from them as they receive values.

module Main where

import Prelude

import Effect (Effect)
import Effect.Console (log)
import Effect.Aff (Aff, launchAff_, delay)
import Effect.Class (liftEffect)
import Control.Parallel (parallel, runParallel)
import Data.Time.Duration (Milliseconds(..))

-- Simulate a channel with a function that returns a value after a delay
simulateChannel :: String -> Int -> Aff String
simulateChannel msg delayMs = do
  delay (Milliseconds $ toNumber delayMs)
  pure msg

main :: Effect Unit
main = launchAff_ do
  -- Create two "channels"
  let c1 = simulateChannel "one" 1000
      c2 = simulateChannel "two" 2000

  -- Use parallel to simulate selecting from multiple channels
  result <- runParallel $ parallel c1 <|> parallel c2
  liftEffect $ log $ "received " <> result

  -- Wait for the second result
  result2 <- runParallel $ parallel c2 <|> parallel c1
  liftEffect $ log $ "received " <> result2

In this example, we’re simulating channels using functions that return values after a delay. The simulateChannel function takes a message and a delay in milliseconds, and returns the message after the specified delay.

We create two “channels”, c1 and c2, which will return their values after 1 and 2 seconds respectively.

To simulate selecting from multiple channels, we use the parallel function from Control.Parallel. The <|> operator is used to race the parallel computations against each other, similar to how select works in other languages.

We run this twice to get both results, simulating a loop that selects from the channels multiple times.

To run this program, you would typically use the PureScript compiler (purs) to compile it, and then execute it with Node.js:

$ spago build
$ node -e "require('./output/Main').main()"
received one
received two

Note that the total execution time is only about 2 seconds since both the 1 and 2 second delays execute concurrently.

This example demonstrates how to work with asynchronous operations and select from multiple concurrent computations in PureScript, providing similar functionality to channels and select statements in other languages.