Range Over Channels in Standard ML

(* In a previous example we saw how iteration works over basic data structures.
   We can also use similar syntax to iterate over values received from a channel. *)

(* In Standard ML, we don't have built-in channels like in some other languages.
   Instead, we'll simulate this behavior using a queue implemented as a list. *)

fun main() =
    let
        (* We'll iterate over 2 values in the `queue` list. *)
        val queue = ["one", "two"]

        (* This function simulates receiving elements from a channel *)
        fun receive [] = NONE
          | receive (x::xs) = SOME(x, xs)

        (* This function simulates iterating over the queue *)
        fun iterate [] = ()
          | iterate q =
            case receive q of
                NONE => ()
              | SOME(elem, rest) =>
                    (print (elem ^ "\n");
                     iterate rest)
    in
        iterate queue
    end

(* Run the main function *)
val _ = main()

To run the program, save it as range_over_channels.sml and use a Standard ML compiler like MLton:

$ mlton range_over_channels.sml
$ ./range_over_channels
one
two

This example demonstrates how to simulate iterating over a channel-like structure in Standard ML. Since Standard ML doesn’t have built-in channels or a range construct like some other languages, we’ve implemented a simple queue using a list and created functions to mimic receiving and iterating over elements.

The receive function simulates receiving an element from the queue, returning an option type that’s either NONE (for an empty queue) or SOME(element, rest_of_queue) for a non-empty queue.

The iterate function recursively processes the queue, printing each element until the queue is empty.

This approach showcases how we can adapt concepts from other languages to work within the constraints and idioms of Standard ML.