Maybe the thing you’re looking for is GADT’s
(* Given:
module Db : sig
type t
module Row : sig
type t
val get_int : t -> int -> int
val get_string : t -> int -> string
end
val query : t -> string -> Row.t list
end
*)
type _ column =
| Dep_id of int column
| Name of string column
let to_column_name : type a. a column -> string = function
| Dep_id -> "dep_id"
| Name -> "name"
(* `read_all db Dep_id` returns an `int list` of all values in dep_id, and
`read_all db Name` returns a `string` list of all values in `name` *)
let read_all db : type a. a column -> a list =
let query = Printf.sprintf "SELECT %s FROM some_table"
(to_column_name column) in
Db.query db query
|> List.map ~f:(fun row ->
match column with
| Dep_id -> Db.Row.get_int row 0
| Name -> Db.Row.get_name row 0
Beyond that, maybe you’d need to look into PPX.