OCaml:为什么重命名类型失败 "Their kinds differ"
OCaml: Why does renaming a type fail with "Their kinds differ"
我正在为成对的类型见证和见证类型的值构建一个通用容器。我想将其用于几种不同的类型,这会给我带来错误,因为这些类型的名称都相同。
所以我正在尝试重命名仿函数结果中的类型,如下所示:
module type Witness = sig type 'a key type 'a value end
module type Witnessed = sig
type 'a key
type 'a value
type t
type ('a, 'b) conv = {
key : 'c . 'c key -> 'a;
value : 'c . 'c value -> 'b;
}
val box : 'a key -> 'a value -> t
val conv : ('a, 'b) conv -> t -> ('a * 'b)
end
module MAKE(W : Witness) : Witnessed with type 'a key = 'a W.key
and type 'a value = 'a W.value = struct
include W
type t = Box : 'a key * 'a value -> t
let box k v = Box (k, v)
type ('a, 'b) conv = {
key : 'c . 'c key -> 'a;
value : 'c . 'c value -> 'b;
}
let conv conv (Box (k, v)) = (conv.key k, conv.value v)
end
type _ token
type _ attrib
module W = struct
type 'a key = 'a token
type 'a value = 'a attrib
end
module Boxed = struct
module T = MAKE(W)
type lexeme = T.t
type ('a, 'b) lexeme_conv = ('a, 'b) T.conv
include (T : module type of T with type 'a key := 'a token
and type 'a value := 'a attrib
and type t := lexeme
and type ('a, 'b) conv := ('a, 'b) lexeme_conv)
end
并且 ocaml 说:
File "foo.ml", line 49, characters 38-80:
Error: This variant or record definition does not match that of type
('a, 'b) lexeme_conv
Their kinds differ.
conv 和 lexeme_conv 的类型有何不同?
您可以通过将 lexeme_conv 的定义替换为:
来解决问题
type ('a, 'b) lexeme_conv = ('a, 'b) T.conv = {
key : 'c . 'c T.key -> 'a;
value : 'c . 'c T.value -> 'b;
}
这是因为类型别名和类型定义在破坏性替换方面的行为方式不同。例如,这里使用 lexeme_conv 别名,签名将更改(因为记录定义将停止公开),这是被禁止的。
我正在为成对的类型见证和见证类型的值构建一个通用容器。我想将其用于几种不同的类型,这会给我带来错误,因为这些类型的名称都相同。
所以我正在尝试重命名仿函数结果中的类型,如下所示:
module type Witness = sig type 'a key type 'a value end
module type Witnessed = sig
type 'a key
type 'a value
type t
type ('a, 'b) conv = {
key : 'c . 'c key -> 'a;
value : 'c . 'c value -> 'b;
}
val box : 'a key -> 'a value -> t
val conv : ('a, 'b) conv -> t -> ('a * 'b)
end
module MAKE(W : Witness) : Witnessed with type 'a key = 'a W.key
and type 'a value = 'a W.value = struct
include W
type t = Box : 'a key * 'a value -> t
let box k v = Box (k, v)
type ('a, 'b) conv = {
key : 'c . 'c key -> 'a;
value : 'c . 'c value -> 'b;
}
let conv conv (Box (k, v)) = (conv.key k, conv.value v)
end
type _ token
type _ attrib
module W = struct
type 'a key = 'a token
type 'a value = 'a attrib
end
module Boxed = struct
module T = MAKE(W)
type lexeme = T.t
type ('a, 'b) lexeme_conv = ('a, 'b) T.conv
include (T : module type of T with type 'a key := 'a token
and type 'a value := 'a attrib
and type t := lexeme
and type ('a, 'b) conv := ('a, 'b) lexeme_conv)
end
并且 ocaml 说:
File "foo.ml", line 49, characters 38-80:
Error: This variant or record definition does not match that of type
('a, 'b) lexeme_conv
Their kinds differ.
conv 和 lexeme_conv 的类型有何不同?
您可以通过将 lexeme_conv 的定义替换为:
来解决问题type ('a, 'b) lexeme_conv = ('a, 'b) T.conv = {
key : 'c . 'c T.key -> 'a;
value : 'c . 'c T.value -> 'b;
}
这是因为类型别名和类型定义在破坏性替换方面的行为方式不同。例如,这里使用 lexeme_conv 别名,签名将更改(因为记录定义将停止公开),这是被禁止的。