Frage

Why can't I coerce record types in OCaml? Base types like int works fine.

Below is an example where I construct a base module M which I include in module A. M.t is type abbriviated in A. As long as M.t is int, I can do A.t' :> M.t. When I change it to {i : int}, the compiler says it's not a subtype. I'm guessing there is a very specific reason for this?

module M = struct
  type t = {i : int}
  let make () = {i = 10}
end

module A : sig
  include module type of M
  type t' = private t
  val make : unit -> t'
end = struct
  include M
  type t' = t
end

In the toplevel:

(A.make() :> M.t);;
Error: Type A.t' is not a subtype of M.t 
War es hilfreich?

Lösung

That's because A.t' has no relation to M.t, because include does not "preserve" equality, it just literally duplicates the module structure (or signature) and inlines it in place (as fresh types and values). So type M.t doesn't have any relation to A.t and therefore to A.t' (and different record types do not have structural subtyping defined like say objects or modules). Obvious fix is type t' = private M.t.

UPDATE

It appears the above is not fully correct, because type t' = private M.t in signature and include M type t' = t in implemention do typecheck, so include M preserves the equality (otherwise it couldn't match the signature type t' = private M.t), unlike copypasting the contents of M in the place of include M. But this "obviously" doesn't hold for include module type of which creates fresh types..

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top