如何修复将类型注释与functor一起使用时出现的OCaml编译错误?
我是OCaml新手,我正在尝试使用函子。当我对functor使用模块类型注释时,这会导致代码中出现编译时错误 当我删除如何修复将类型注释与functor一起使用时出现的OCaml编译错误?,ocaml,functor,Ocaml,Functor,我是OCaml新手,我正在尝试使用函子。当我对functor使用模块类型注释时,这会导致代码中出现编译时错误 当我删除:Printable(从模块FromToString行)和:ToString(从模块IntToString行)注释时,以下程序编译无误: module type ToString = sig type t val to_string: t -> string end module type Printable = sig type t va
:Printable
(从模块FromToString
行)和:ToString
(从模块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
如何使用这些注释而不导致编译错误?根本问题是您的签名约束使生成的模块过于不透明。约束函子结果时:
module FromToString (S:ToString) : Printable = ...
您正在使类型t
成为一个抽象类型,它只能由to_string
函数使用,并且永远不会生成。换句话说,类型为Printable
的模块本身不可用
从functor开始时,查看编译器为生成的模块推断的模块类型通常非常有用。
在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
它非常类似于可打印
,只是现在类型t
等于参数模块S
的类型t
因此,通过添加一个带有约束的类型等式,可以重用可打印的来写入结果的完整模块类型:
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
根本问题是签名约束使生成的模块过于不透明。约束函子结果时:
module FromToString (S:ToString) : Printable = ...
您正在使类型t
成为一个抽象类型,它只能由to_string
函数使用,并且永远不会生成。换句话说,类型为Printable
的模块本身不可用
从functor开始时,查看编译器为生成的模块推断的模块类型通常非常有用。
在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
它非常类似于可打印
,只是现在类型t
等于参数模块S
的类型t
因此,通过添加一个带有约束的类型等式,可以重用可打印的来写入结果的完整模块类型:
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
必须使用带有
符号的将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 3
必须使用带有
符号的将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 3