Maps in Standard ML

Maps are Standard ML’s built-in associative data type, sometimes called dictionaries in other languages.

To create an empty map, use an association list [ (key1, val1), (key2, val2) ].

(* Creating an empty list (used as a map) *)
val m = ref ([] : (string * int) list)

Set key/value pairs using typical (name, key) :: map syntax.

(* Setting key/value pairs *)
val () = m := ("k1", 7) :: !m
val () = m := ("k2", 13) :: !m

Printing a map will show all of its key/value pairs.

(* Printing the map *)
val () = print ("map: " ^ concat (map (fn (k, v) => k ^ ":" ^ Int.toString(v) ^ " ") !m) ^ "\n")

Get a value for a key with List.find.

(* Getting a value for a key *)
val v1 = List.find (fn (k, _) => k = "k1") (!m)
val () = (case v1 of SOME (_, v) => print ("v1: " ^ Int.toString(v) ^ "\n") | NONE => ())

If the key doesn’t exist, the zero value of the value type is returned.

(* Getting a key that doesn't exist *)
val v3 = List.find (fn (k, _) => k = "k3") (!m)
val () = (case v3 of SOME (_, v) => print ("v3: " ^ Int.toString(v) ^ "\n") | NONE => print "v3: 0\n")

The List.length function returns the number of key/value pairs when called on a map.

(* Getting the length of the map *)
val () = print ("len: " ^ Int.toString (List.length (!m)) ^ "\n")

To remove a key/value pair, use List.filter.

(* Deleting a key/value pair *)
val () = m := List.filter (fn (k, _) => k <> "k2") (!m)
val () = print ("map: " ^ concat (map (fn (k, v) => k ^ ":" ^ Int.toString(v) ^ " ") !m) ^ "\n")

To remove all key/value pairs from a map, simply set it to an empty list.

(* Clearing all key/value pairs *)
val () = m := []
val () = print ("map: " ^ concat (map (fn (k, v) => k ^ ":" ^ Int.toString(v) ^ " ") !m) ^ "\n")

You can also declare and initialize a new map in the same line with association list syntax.

(* Initializing and printing a new map *)
val n = [("foo", 1), ("bar", 2)]
val () = print ("map: " ^ concat (map (fn (k, v) => k ^ ":" ^ Int.toString(v) ^ " ") n) ^ "\n")

To check if two maps are equal, you can use the List.all function.

(* Checking if two maps are equal *)
val n2 = [("foo", 1), ("bar", 2)]
val equal = List.all (fn (k, v) => List.exists (fn (k2, v2) => k = k2 andalso v = v2) n) n2 andalso
            List.all (fn (k, v) => List.exists (fn (k2, v2) => k = k2 andalso v = v2) n2) n
val () = if equal then print ("n == n2\n") else ()

Note that maps appear as a printed list of key/value tuples when printed with print.

Running the program will output:

map: k2:13 k1:7 
v1: 7
v3: 0
len: 2
map: k1:7 
map: 
prs: false
map: bar:2 foo:1 
n == n2

Now that we can run and build basic Standard ML programs, let’s learn more about the language.