Channel Directions in Standard ML
(* When using channels as function parameters in Standard ML, we can use
ref types to simulate send-only or receive-only channels. This specificity
increases the type-safety of the program. *)
(* This `ping` function only accepts a channel for sending values. *)
fun ping (pings: string option ref, msg: string) =
pings := SOME msg
(* The `pong` function accepts one channel for receives (pings)
and a second for sends (pongs). *)
fun pong (pings: string option ref, pongs: string option ref) =
case !pings of
SOME msg => pongs := SOME msg
| NONE => ()
(* Main function to demonstrate the usage *)
fun main () =
let
val pings = ref NONE
val pongs = ref NONE
in
ping (pings, "passed message");
pong (pings, pongs);
case !pongs of
SOME msg => print (msg ^ "\n")
| NONE => print "No message received\n"
end
(* Run the main function *)
val _ = main ()In Standard ML, we don’t have built-in channels like in some other languages. However, we can simulate similar behavior using reference types (ref) and options. Here’s how the code works:
We define
pingandpongfunctions that operate onstring option reftypes. These act as our “channels”.The
pingfunction takes a “send-only” channel (pings) and a message. It updates the reference with the message.The
pongfunction takes a “receive-only” channel (pings) and a “send-only” channel (pongs). It reads frompingsand writes topongs.In the
mainfunction, we create two references to simulate channels, then callpingandpong, and finally print the result.
To run this program, you would typically save it in a file (e.g., channel_directions.sml) and then use an SML interpreter or compiler. For example, with Standard ML of New Jersey (SML/NJ):
$ sml channel_directions.sml
passed messageThis example demonstrates how to simulate channel-like behavior in Standard ML, even though the language doesn’t have built-in support for channels. The use of reference types and options allows us to create a similar send/receive paradigm.