First class module signature mismatch

For what it’s worth, it turns out that GADTs were counter-productive to reach my ultimate goal. I could never “curry” with them, with yet another a b not included in 'a b kind of error in the use of signature I. A plain private variant turned out to work with my cleaned up structure. The relevant bits:

module Buf = struct
  (* types bigstring_buf, buffer_buf, bytes_buf, string_buf *)
  type t =
    | Bigstring_buf of bigstring_buf
    | Buffer_buf of buffer_buf
    | Bytes_buf of bytes_buf
    | String_buf of string_buf

  module type S = sig
    val length : unit -> int
  end

  module Make_bytes (I : sig
    val b : bytes_buf
  end) : S = struct
    let length () = Bytes.length I.b.data
  end
  (* Make_bigstring(), Make_buffer(), Make_string() ... *)

  let get_module bt =
    match bt with
    | Bytes_buf b -> (module Make_bytes (struct let b = b end) : S)
    (* ... *)

end

module Some_codec = struct
  let decode src dst =
    let module In = (val Buf.get_module src) in
    let module Out = (val Buf.get_module dst) in
    (* Use In and Out ... *)
    dst

  let test str = str |> Buf.of_string |> decode (Buf.new_buffer 4096)
  (* val test : string -> Buf.t *)
end

The end result is that not only can Some_codec abstract away the input and output buffer implementations, but there’s also no run-time cost in doing so after the initial calls to Buf.get_module.

1 Like