Generics in OCaml

Our example demonstrates the use of parametric polymorphism in OCaml, which is similar to generics in other languages.

(* The 'index' function takes a list of any type 'a and a value of type 'a,
   and returns the index of the first occurrence of the value in the list,
   or -1 if not present. The 'a constraint ensures that we can compare values
   of this type with the '=' operator. *)
let rec index (lst : 'a list) (v : 'a) : int =
  match lst with
  | [] -> -1
  | hd :: tl -> if hd = v then 0 else 1 + index tl v

(* Define a generic list type *)
type 'a my_list = {
  mutable head : 'a node option;
  mutable tail : 'a node option;
}
and 'a node = {
  mutable next : 'a node option;
  value : 'a;
}

(* Push method for our generic list *)
let push (lst : 'a my_list) (v : 'a) =
  let new_node = { next = None; value = v } in
  match lst.tail with
  | None ->
      lst.head <- Some new_node;
      lst.tail <- Some new_node
  | Some tail ->
      tail.next <- Some new_node;
      lst.tail <- Some new_node

(* Function to get all elements of our generic list *)
let all_elements (lst : 'a my_list) : 'a list =
  let rec aux node acc =
    match node with
    | None -> List.rev acc
    | Some n -> aux n.next (n.value :: acc)
  in
  aux lst.head []

(* Main function to demonstrate usage *)
let () =
  let s = ["foo"; "bar"; "zoo"] in
  Printf.printf "index of zoo: %d\n" (index s "zoo");

  let lst = { head = None; tail = None } in
  push lst 10;
  push lst 13;
  push lst 23;
  Printf.printf "list: [%s]\n" (String.concat "; " (List.map string_of_int (all_elements lst)))

To run this program, save it as generics.ml and use the OCaml compiler:

$ ocamlc -o generics generics.ml
$ ./generics
index of zoo: 2
list: [10; 13; 23]

In this OCaml version:

  1. We define a polymorphic index function that works on lists of any type, similar to the SlicesIndex function in the original example.

  2. We create a custom my_list type to demonstrate generic data structures. This is analogous to the List type in the original example.

  3. The push and all_elements functions are defined for our custom list type, showcasing how to work with generic data structures in OCaml.

  4. In the main part of the program, we demonstrate the usage of these generic functions and data structures.

Note that OCaml has built-in support for parametric polymorphism, which is similar to generics in other languages. The 'a type variable in our definitions allows the functions and types to work with any type.