Channel Directions in F#
In F#, we can specify the direction of channels using different types. This specificity increases the type-safety of the program.
open System
// This `ping` function only accepts a channel for sending
// values. It would be a compile-time error to try to
// receive on this channel.
let ping (pings: MailboxProcessor<string>) msg =
pings.Post msg
// The `pong` function accepts one channel for receives
// (`pings`) and a second for sends (`pongs`).
let pong (pings: MailboxProcessor<string>) (pongs: MailboxProcessor<string>) =
async {
let! msg = pings.Receive()
pongs.Post msg
}
[<EntryPoint>]
let main argv =
let pings = MailboxProcessor.Start(fun _ -> async { return () })
let pongs = MailboxProcessor.Start(fun _ -> async { return () })
ping pings "passed message"
pong pings pongs |> Async.RunSynchronously
let result = pongs.Receive() |> Async.RunSynchronously
printfn "%s" result
0 // return an integer exit code
In this F# version:
We use
MailboxProcessor<'T>
as an equivalent to Go’s channels.MailboxProcessor
is F#’s built-in implementation of the actor model, which provides similar functionality to channels.The
ping
function takes aMailboxProcessor<string>
for sending and uses thePost
method to send a message.The
pong
function takes twoMailboxProcessor<string>
instances, one for receiving (pings
) and one for sending (pongs
). It uses an async workflow to receive a message frompings
and then post it topongs
.In the
main
function, we create twoMailboxProcessor
instances usingMailboxProcessor.Start
. We then callping
andpong
, and finally receive and print the result.We use
Async.RunSynchronously
to run the asynchronous operations synchronously in this example.
To run the program, save it as ChannelDirections.fs
and use the F# compiler:
$ fsharpc ChannelDirections.fs
$ mono ChannelDirections.exe
passed message
This example demonstrates how F# can achieve similar functionality to Go’s channel directions using MailboxProcessor
and its type system.