首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修复与函子一起使用类型注释时的OCaml编译错误?

如何修复与函子一起使用类型注释时的OCaml编译错误?
EN

Stack Overflow用户
提问于 2019-01-18 08:57:24
回答 2查看 192关注 0票数 0

我是OCaml的新手,我正在尝试使用函子。当我在函子中使用模块类型注释时,这会导致代码中的编译时错误。

当我删除: Printable (从module FromToString行)和: ToString (从module IntToString行)注释时,以下程序编译时没有出错:

代码语言:javascript
复制
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

但是,当我添加这些注释(如代码所示)时,编译器会出现以下错误:

代码语言:javascript
复制
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

如何在不导致编译错误的情况下使用这些注释?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-18 12:10:12

根本的问题是,您的签名约束使得结果模块过于不透明。当约束函子结果时:

代码语言:javascript
复制
 module FromToString (S:ToString) : Printable = ...

您正在使类型t成为一个抽象类型,该类型只能由to_string函数使用,而且从未生成。换句话说,Printable类型的模块本身是不可用的。

从函子开始时,查看编译器为得到的模块推断的模块类型通常是有用的。在FromToString的情况下,这是:

代码语言:javascript
复制
module FromToString (S:ToString) : sig
  type t = S.t
  val print: t -> unit
end = ...

您可以看到结果的推断模块类型。

代码语言:javascript
复制
 sig
   type t = S.t
   val print: t -> unit
 end

它非常类似于Printable,只不过现在类型t等于参数模块St类型。

因此,通过添加带有Printable约束的类型相等,可以重用with来编写结果的完整模块类型:

代码语言:javascript
复制
  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上,可以用类似的方式解决:

代码语言:javascript
复制
module IntToString : ToString with type t = int =
struct
    type t = int
    let to_string = string_of_int
end

然后编译器错误就消失了:

代码语言:javascript
复制
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
票数 2
EN

Stack Overflow用户

发布于 2019-01-18 12:11:26

必须使用with符号将t类型公之于众:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54250519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档