Do you know about separate tagging in OCaml ? That is avoiding boxing by having a tag and its attached payload in separate values. I will show a very simple example, but it is surprising what you can achieve with it.
Here is an example of the different ways of programming a function that take either a float or an int and return the closest int.
type my_adt = TI of int | TF of float
(* Safe but uses unnecessary boxing *)
let f_safe = function TI i -> i | TF f -> int_of_float f
type my_tags = TI | TF
(* very unsafe but no useless boxing *)
let f_unsafe tag n =
match tag with
| TI ->
(Obj.magic n : int)
| TF ->
int_of_float (Obj.magic n : float)
type _ my_gadt = TI : int my_gadt | TF : float my_gadt
(* Same runtime behaviour as f_unsafe, but safe. *)
let f_gadt : type t. t my_gadt -> t -> int =
fun tag n ->
match tag with
| TI -> n
| TF -> int_of_float n