Hello,
I have some troubles using GADTs for a future project targeting Node with BuckleScript.
This project will use some Node libraries, and I would like to make the bindings flexible and as robust and type safe as possible.
In order to achieve these objectives, I thought about making (1) a “DSL” that would ease the build of a rather complex record, featuring some dynamical heterogeneous lists (hence the use of GADT), and deeply nested records, and (2) a “parser” for this object that would actually call the JavaScript functions (using extern
and all).
But I’m currently facing a “The type constructor * would escape its scope” error.
Here is a small piece of code showing what I’m currently doing:
(* (1) *)
(* BuckleScript does not support OCaml's record literal in GADTs declaration, hence the *_record boilerplate *)
type ('a, 'b) y_record = { f: 'a -> 'b }
(* 'b seems to "escape" in the transform function below *)
type _ y = Y : ('a, 'b) y_record -> 'a y
type 'a x_record = { list: 'a y list }
type _ x = X : 'a x_record -> 'a x
(* Arbitrary use `int` here *)
let x: int x = X {
list= [
Y {f= (fun _ -> 42)};
Y {f= (fun _ -> "foo")};
]
}
type z
external jsFunction: 'a -> z = ""
(* (2) *)
(* Raises "The type constructor b#11 would escape its scope" *)
let transform: type a. a x -> z = (fun (X x) ->
jsFunction (x.list |> List.map (fun (Y {f}) -> f))
)
After some readings, like this super nice article, and the chapter 8 of the Ocaml manual, even if I somewhat understand what I’m doing wrong, I can’t really figure a way to (1) get rid off the error while keeping the same architecture or (2) find an other way to achieve the same objectives…
Any help would be greatly appreciated!
Edit: Made example closer from the actual code