To enable tail recursion, the ocaml batteries library uses a mutable accumulator in the list module:
type 'a mut_list = {
hd: 'a;
mutable tl: 'a list
}
external inj : 'a mut_list -> 'a list = "%identity"
module Acc = struct
let dummy () =
{ hd = Obj.magic (); tl = [] }
let create x =
{ hd = x; tl = [] }
let accum acc x =
let cell = create x in
acc.tl <- inj cell;
cell
end
It seems like the mutable list is simply cast to the immutable list type, but mut_list and list do not have the same type definition.
Is this safe? How and why does this code work?
The OCaml manual describes the memory layout for various types. For records:
And for variants:
From this we can infer that the
::constructor is laid out asThis is because the
::constructor is the first non-constant constructor, thus tagged "0", followed by its arguments.The mutable record is laid out the same way, since records are always tagged "0" followed by the contents in order.
From these, we can infer that this use of
%identitydoes what we want.