I’m trying to construct a variant type which contains a map that uses the variant type as a key.
open Base
module rec T : sig
type t =
| Int of int
| Table of t Map.M(T).t
[@@deriving compare, sexp]
include Comparator.S with type t := t
end = struct
type t =
| Int of int
| Table of t Map.M(T).t
[@@deriving compare, sexp]
include Comparator.Make(T)
end
include T
I’ve been using the Map module from Base, but I’m running into an error:
Error: Cannot safely evaluate the definition
of the recursively-defined module T
I think this is because Comparator.Make() creates a val comparator : (t, comparator_witness) comparator so T isn’t a safe module. Any ideas on how to get around this?
I came up with a workaround, but I have little experience with Base, Core and TypeConv and so not sure this corresponds to the intended use of the libraries in such cases:
open Base
module type T0 = sig type t [@@deriving compare, sexp] end;;
module rec T0 : sig
type comparator_witness
type t =
| Int of int
| Table of (T0.t, t, comparator_witness) Map.t
[@@deriving compare, sexp]
val comparator : unit -> (t, comparator_witness) Comparator.t
end = struct
module U = struct include (T0 : T0 with type t = T0.t) include Comparator.Make (T0) end
type t =
| Int of int
| Table of t Map.M (U).t
[@@deriving compare, sexp]
type comparator_witness = U.comparator_witness
let comparator () = U.comparator
end;;
module T1 = struct include T0 let comparator = T0.comparator () end;;
module T = struct
type t = T1.t =
| Int of int
| Table of T1.t Map.M(T1).t
include (T1 : module type of T1 with type t := t)
end;;
T.compare (T.Int 0) (T.Table (Map.of_alist_exn (module T) [T.Int 0, T.Int 1]));;
T.sexp_of_t (T.Table (Map.of_alist_exn (module T) [T.Int 0, T.Int 1]));;