Channel Directions in PureScript
PureScript doesn’t have built-in channels like Go, but we can simulate similar behavior using the Effect
monad and Ref
s. Here’s an equivalent implementation:
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
import Effect.Ref as Ref
-- This `ping` function only accepts a function for sending
-- values. It would be a type error to try to receive using this function.
ping :: (String -> Effect Unit) -> String -> Effect Unit
ping send msg = send msg
-- The `pong` function accepts one function for receives
-- and a second for sends.
pong :: Effect String -> (String -> Effect Unit) -> Effect Unit
pong receive send = do
msg <- receive
send msg
main :: Effect Unit
main = do
pings <- Ref.new ""
pongs <- Ref.new ""
let sendPing = Ref.write pings
receivePing = Ref.read pings
sendPong = Ref.write pongs
receivePong = Ref.read pongs
ping sendPing "passed message"
pong receivePing sendPong
result <- receivePong
log result
When using functions as parameters in PureScript, you can specify if a function is meant to only send or receive values. This specificity increases the type-safety of the program.
The ping
function only accepts a function for sending values. It would be a type error to try to receive using this function.
The pong
function accepts one function for receives and a second for sends.
In the main
function, we create two Ref
s to simulate channels. We then define send and receive functions for each “channel” using Ref.write
and Ref.read
respectively.
To run this program, you would typically compile it with the PureScript compiler and then run it with Node.js:
$ spago build
$ node -e "require('./output/Main').main()"
passed message
This example demonstrates how to implement unidirectional communication patterns in PureScript, similar to channel directions in other languages. While PureScript doesn’t have built-in channels, we can achieve similar functionality using its powerful type system and effect handling capabilities.