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 codeIn this F# version:
We use
MailboxProcessor<'T>as an equivalent to Go’s channels.MailboxProcessoris F#’s built-in implementation of the actor model, which provides similar functionality to channels.The
pingfunction takes aMailboxProcessor<string>for sending and uses thePostmethod to send a message.The
pongfunction takes twoMailboxProcessor<string>instances, one for receiving (pings) and one for sending (pongs). It uses an async workflow to receive a message frompingsand then post it topongs.In the
mainfunction, we create twoMailboxProcessorinstances usingMailboxProcessor.Start. We then callpingandpong, and finally receive and print the result.We use
Async.RunSynchronouslyto 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 messageThis example demonstrates how F# can achieve similar functionality to Go’s channel directions using MailboxProcessor and its type system.