I recently ran into a situation with packed GADTs where technically TRMC is implementable, but I’m not sure if it’s doable with the features OCaml currently provides. Here’s a simplified example:
module List_with_length = struct
type ('a, 'length) t =
| [] : ('a, unit) t
| (::) : 'a * ('a, 'length) t -> ('a, unit * 'length) t
type 'a packed = T : ('a, _) t -> 'a packed [@@unboxed]
(* [of_list] can return any length, so we need to return a packed version.
This seems to mean that I cannot use TMRC.
*)
let rec of_list (list : 'a list) =
match list with
| [] -> T []
| hd :: tl ->
(match of_list tl with
| T tl -> T (hd :: tl))
;;
end
Because packed
is unboxed, from a runtime, post type-erasure perspective, this is a classic case TRMC. But because of the packing, I have to match on the recursive call, which means the call is no longer in the tail position. Is this doable? If not should we look into adding support for this specific pattern into the compiler (treat a match on a recursive call where the result of the match is a single branch whose expression is TRMC constructible as a tail call)?