Custom Type Polymorphic Map

I am trying to understand the type system, and I am running into something I cannot get around but I feel like I should be able to. Below is a minimal example below of what I want to be able to do.

type example_type = 
  | IntList of int list
  | StringList of string list

let intlist = IntList [1;2;3]
let stringlist = StringList ["a";"b";"C"]

let map_test x f =
   match x with 
       | IntList c -> List.map c ~f:f
       | StringList c -> List.map c ~f:f

List.map_test intlist ~f:(fun x -> x + 1)

Is there a way to build the map_test function in a way that will type check? Is there any way to build a polymorphic map function that works on the example_type?

If providing an answer, if you could also include a link to info or the vocabulary I should search for to learn more about solving this type of problem that would be really helpful.

type _ example_type =
  | IntList : int list -> int example_type
  | StringList : string list -> string example_type

let intlist = IntList [ 1; 2; 3 ]
let stringlist = StringList [ "a"; "b"; "C" ]

let map_test : type a. a example_type -> (a -> 'b) -> 'b list =
 fun x f ->
  match x with
  | IntList c -> List.map f c
  | StringList c -> List.map f c
;;

let _ = map_test intlist (fun x -> x + 1)
let _ = map_test stringlist (fun x -> String.capitalize_ascii x)

It is called GADT, more on Real World OCaml: GADTs - Real World OCaml

2 Likes