我是OCaml的新手,我正在尝试使用函子。当我在函子中使用模块类型注释时,这会导致代码中的编译时错误。
当我删除: Printable (从module FromToString行)和: ToString (从module IntToString行)注释时,以下程序编译时没有出错:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3但是,当我添加这些注释(如代码所示)时,编译器会出现以下错误:
File "Functor.ml", line 26, characters 28-29:
Error: This expression has type int but an expression was expected of type
PrintableInt.t = FromToString(IntToString).t如何在不导致编译错误的情况下使用这些注释?
发布于 2019-01-18 12:10:12
根本的问题是,您的签名约束使得结果模块过于不透明。当约束函子结果时:
module FromToString (S:ToString) : Printable = ...您正在使类型t成为一个抽象类型,该类型只能由to_string函数使用,而且从未生成。换句话说,Printable类型的模块本身是不可用的。
从函子开始时,查看编译器为得到的模块推断的模块类型通常是有用的。在FromToString的情况下,这是:
module FromToString (S:ToString) : sig
type t = S.t
val print: t -> unit
end = ...您可以看到结果的推断模块类型。
sig
type t = S.t
val print: t -> unit
end它非常类似于Printable,只不过现在类型t等于参数模块S的t类型。
因此,通过添加带有Printable约束的类型相等,可以重用with来编写结果的完整模块类型:
module FromToString (S:ToString): Printable with type t = S.t = struct
type t = S.t
let print a = print_string ( S.to_string a)
end同样的问题出现在IntToString上,可以用类似的方式解决:
module IntToString : ToString with type t = int =
struct
type t = int
let to_string = string_of_int
end然后编译器错误就消失了:
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3发布于 2019-01-18 12:11:26
必须使用with符号将t类型公之于众:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable with type t = S.t =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString with type t =int =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3https://stackoverflow.com/questions/54250519
复制相似问题