Types 包含一个模块将吞咽其类型
我有以下资料: 带有获取姓名方法的Types 包含一个模块将吞咽其类型,types,module,ocaml,Types,Module,Ocaml,我有以下资料: 带有获取姓名方法的人员模块类型: module type Person = sig type t val first : t -> string val last : t -> string end PersonUtilsfunctor,用于使用name函数扩展Person: module PersonUtils (Person: Person) : sig type t val name : t -> string end = struc
人员
模块类型:
module type Person = sig
type t
val first : t -> string
val last : t -> string
end
PersonUtils
functor,用于使用name
函数扩展Person
:
module PersonUtils (Person: Person) : sig
type t
val name : t -> string
end = struct
include Person
let name p = Person.first p ^ " " ^ Person.last p
end
和主
模块,如下所示:
module Main : sig
type t
val name : t -> string
end = struct
include PersonUtils(struct
type t = {
first: string;
last: string;
}
let first p = p.first
let last p = p.last
end)
end
在Main
中,我想添加一个额外的loud\u first\u name
函数:因此我将以下内容添加到签名和模块中:
module Main : sig
type t
val name : t -> string
(* New *)
val loud_first_name : t -> string
end = struct
include PersonUtils(struct
type t = {
first: string;
last: string;
}
let first p = p.first
let last p = p.last
end)
(* New *)
let loud_first_name p = String.uppercase p.first
end
但是,loud\u first\u name
似乎不再知道我的类型t
的结构,因此我只剩下错误Unbound record field first
我的问题是:如何创建像loud\u first\u name
这样的方法,以便它们仍然可以访问我的记录字段?我试图将我的t
类型向上移动一个级别,但在我的函子的参数中使用它时遇到了问题
module Main : sig
type t
val name : t -> string
val loud_first_name : t -> string
end = struct
type t_ = {
first: string;
last: string;
}
include PersonUtils(struct
type t = t_
let first p = p.first
let last p = p.last
end)
(* Signature mismatch:
...
Values do not match:
val loud_first_name : t_ -> string
is not included in
val loud_first_name : t -> string
*)
let loud_first_name p = String.uppercase p.first
end
您必须在签名中指出您的类型是相同的,如果您仅在结构中指出,则信息将丢失
module PersonUtils (Person: Person) : sig
type t = Person.t
val name : t -> string
end
= struct
include Person
let name p = Person.first p ^ " " ^ Person.last p
end
另一种方法(我推荐)是在模块类型声明中添加with
子句
module PersonUtils (Person: Person) : sig
type t
val name : t -> string
end
with type t = Person.t
= struct
include Person
let name p = Person.first p ^ " " ^ Person.last p
end
虽然信息在签名声明中不直接可见,但它允许您单独声明签名和函子:
module type Personutils_T = sig
type t
val name : t -> string
end
module PersonUtils (Person: Person) : Personutils_T
with type t = Person.t
= struct
include Person
let name p = Person.first p ^ " " ^ Person.last p
end
看起来像是
类型nonrec t=t
(谢谢)的组合,包括带有签名的模块修复了我的问题
module type PUSig = sig
type t
val name : t -> string
end
module PersonUtils (Person: Person) : PUSig with type t = Person.t = struct
include Person
let name p = Person.first p ^ " " ^ Person.last p
end
module Main : sig
type t = {
first: string;
last: string;
}
val loud_first_name : t -> string
end = struct
type t = {
first: string;
last: string;
}
include (PersonUtils(struct
type nonrec t = t
let first p = p.first
let last p = p.last
end) : PUSig with type t := t)
(* New *)
let loud_first_name p = String.uppercase_ascii p.first
end
谢谢在上一个示例中,我能够消除签名不匹配。但是有什么方法可以避免t=t类型?如果我内联
type t={first:string;…}
那么我的loud\u first\u name
方法仍然无法查看其字段。您可以尝试type nonrec t=t
。它将引用范围中的t
,而不是定义中的。谢谢@ÉtienneMillon!我不知道这个语法。不过,我包含的模块会导致我的typet
重复(并且我会收到一条错误消息)。也许我使用的包括不正确?明白了<代码>包含
ing my module:类型为t:=t的Sig
修复了该问题以及类型为nonrec t=t
。非常感谢!