To expand slightly on Jacques' answer. Record fields (and variant constructors) must be explicitly exported, using the: type t = Foo.t = { bar : int } syntax. For example, the following version of your example works: module type HasType = sig type t = { innerRecordField: int } end module EchoModule (Input : HasType) : HasType with type t = Input.t = struct type t = Input.t = {innerRecordField: int} end module ClonedModuleWithRecordType = EchoModule(struct type t = {innerRecordField: int} end) let myRecord: ClonedModuleWithRecordType.t = { ClonedModuleWithRecordType.innerRecordField=10; } Of course, the `EchoModule` functor can now only operate on modules where the type t is defined as: type t = { innerRecordField : int } Jacques' solution of giving the functor argument a name, and using that name to access the field, is a much more flexible approach. Regards, Leo On Sun, 10 May 2015, at 05:58 PM, Jordan W wrote: > I believe there is an issue with record fields and functors. It > appears that while types are correctly exported from functors, the > corresponding record field scopes are not. Here is an example. > > module type HasType = sig type t end > > module EchoModule (Input:HasType): (HasType with type t = Input.t) = > (struct type t = Input.t end) > > module ClonedModuleWithRecordType = EchoModule (struct type t = > {innerRecordField: int} end) > > (* This doesn't type check, but I can't see why it shouldn't. Record > fields' scopes should be reexported just like the types themselves. > > let myRecord: ClonedModuleWithRecordType.t = { > ClonedModuleWithRecordType.innerRecordField=10; } > > In this case, the original "scope" of the record fields is "lost" > because the record type was declared in an anonymous module > expression. I believe that it *should* be "lost" as it is, but then > reexported as an identical type in the module returned from the > functor (identically because of the "with constraint"). > > *) > > module ClonedModuleWithNonRecordType = EchoModule (struct type t = > string list end) > > (* This typechecks perfectly fine! Evidence that types are reexported, > but not the "scope" of record labels *) let myRecord: > ClonedModuleWithNonRecordType.t = ["asdf"; "fff"] > > > Is anyone aware of whether or not this issue is already being tracked? >