2012-05-07 123 views
3

OCaml不能在签名中展开中间参数化类型是否有原因?隐藏签名中的类型参数

例如:

(* foo.ml *) 
type 'a internal = Foo of 'a 
type t = string internal 

和:

(* foo.mli *) 
type t = Foo of string 

给出一个错误。

我想这是相关型号的事实,内存表现形式可以是不同的时候,但是我不知道是否有提交错误报告,OCaml中的bug跟踪器之前的任何更深层次的原因?

+0

对我来说似乎两种't'是一样的,但是两个'Foo'构造函数是不一样的。如果这是正确的,它可能不是关于展开参数化类型以至于'Foo'的冲突定义。 –

回答

4

这不是一个记忆表示问题。当检查时,如果声明t1比声明t2以下一般更一般地匹配针对一种类型的签名,或类型声明,类型检查器目前仅考虑那些三种情况:

  • t2是一个抽象的类型或类型缩写
  • t1t2都和类型
  • t1t2都记录

其他情况下会失败并显示错误。在你的情况下,t1(被检查的类型)是一个类型缩写,并且t2(规范)是一个和类型。这会导致类型错误。

看到源代码:type_declarationstyping/includemod.ml

这是不是一个内存中表示考虑作为foo.ml会失败,这也:

type u = Foo of string 
type t = u 

也许这种检查可以细化。你应该问错误追踪器。

编辑:说明此检查的细化程度并不是微不足道的。这是不一般的正确检查签名匹配时扩大上的签名侧缩写,例如下列不应当被接受的:

module Test : sig 
    type t = Foo 
    type u = t (* to the outside, t and u would be equal *) 
end = struct 
    type t = Foo (* while internally they are different *) 
    type u = Foo (* sum/records are generative/nominative *) 
end 

其他的方式(内部平等从外部隐藏)是正确的并且已经可能的:

module Test : sig 
    type t = Foo 
    type u = Foo 
end = struct 
    type t = Foo 
    type u = t = Foo 
end;; 

fun (x : Test.t) -> (x : Test.u);; 
(* Error: This expression has type Test.t but an expression 
    was expected of type Test.u *) 

现在,内存中的表示考虑缩写扩展时也进入帐户,作为类型系统的动态语义(内存中的表示的选择)不被这样扩展保留:

module Test : sig 
    type r = { x : float; y : float; z : float } (* boxed float record *) 
end = struct 
    type 'a t = { x : 'a; y : 'a; z : 'a } (* polymorphic record *) 
    type r = float t 
end 
5

它可以,只要类型是结构类型,例如,:

type 'a t = 'a * int 
type u = string t 

将匹配

type u = string * int 

然而,变体(和记录)是标称类型OCaml中。也就是说,这种类型的每个声明都会引入新的类型名称。签名中的名义类型规范只能与名义类型声明相匹配,并且必须具有等效的定义。你的例子既不是这样,所以它不被接受。 (这是OCaml中的一个细微角落结构类型的别名和标称类型定义共享相同的语法不帮助的事实。)

FWIW,你也可以重新绑定名义类型:

type 'a t = Foo of 'a 
type 'a u = 'a t = Foo of 'a 

会匹配

type 'a u = Foo of 'a 

但是,这不允许你改变结构或参数,所以不能帮助你的情况。