String Functions in Standard ML

(* The Standard ML basis library provides many useful string-related functions. 
   Here are some examples to give you a sense of the available operations. *)

(* We use the String structure for string operations *)
structure S = String

(* We define a helper function for printing *)
fun p x = print (x ^ "\n")

fun main () =
  let
    (* Here's a sample of the functions available in the String structure.
       These are functions from the structure, not methods on the string itself,
       so we need to pass the string as an argument to the function. *)
    val _ = p ("Contains:  " ^ Bool.toString (S.isSubstring "es" "test"))
    val _ = p ("Count:     " ^ Int.toString (S.size (S.extract ("test", 0, NONE)) - S.size (S.translate (fn c => if c = #"t" then "" else String.str c) "test")))
    val _ = p ("HasPrefix: " ^ Bool.toString (S.isPrefix "te" "test"))
    val _ = p ("HasSuffix: " ^ Bool.toString (S.isSuffix "st" "test"))
    val _ = p ("Index:     " ^ Int.toString (valOf (S.find (fn c => c = #"e") "test")))
    val _ = p ("Join:      " ^ S.concatWith "-" ["a", "b"])
    val _ = p ("Repeat:    " ^ S.implode (List.tabulate (5, fn _ => #"a")))
    val _ = p ("Replace:   " ^ S.translate (fn c => if c = #"o" then "0" else String.str c) "foo")
    val _ = p ("Replace:   " ^ S.map (fn c => if c = #"o" then #"0" else c) "foo")
    val _ = p ("Split:     " ^ String.concatWith " " (S.fields (fn c => c = #"-") "a-b-c-d-e"))
    val _ = p ("ToLower:   " ^ S.map Char.toLower "TEST")
    val _ = p ("ToUpper:   " ^ S.map Char.toUpper "test")
  in
    ()
  end

val _ = main ()

This Standard ML code demonstrates various string operations similar to those in the original example. Here’s an explanation of the differences and adaptations:

  1. Standard ML uses the String structure for string operations, which we alias to S for brevity.

  2. We define a helper function p for printing, similar to the original example.

  3. The main function is defined as a value, not a function, in Standard ML.

  4. Some functions like Contains, Count, and Replace don’t have direct equivalents in Standard ML, so we’ve used alternative implementations:

    • Contains uses isSubstring
    • Count is implemented by comparing the length of the original string with the length after removing all occurrences of the target character
    • Replace is implemented using translate for replacing all occurrences and map for replacing the first occurrence
  5. Split is implemented using fields function, which splits the string based on a predicate function.

  6. ToLower and ToUpper use Char.toLower and Char.toUpper respectively, applied to each character in the string.

To run this program, you would typically save it to a file (e.g., string_functions.sml) and then use an Standard ML interpreter or compiler. For example, with the Standard ML of New Jersey (SML/NJ) system:

$ sml string_functions.sml

This will compile and run the program, displaying the results of various string operations.