签名声明在编译时更改
Signature declaration changed on compilation
当我尝试编译我的代码时,出现以下错误
Error: Signature mismatch:
...
Values do not match:
val filter_map : ('b -> 'b option) -> 'b t -> 'b list
is not included in
val filter_map : ('b -> 'a option) -> 'b t -> 'a list
File "set.ml", line 7, characters 2-55: Expected declaration
File "treeSet.ml", line 105, characters 10-20: Actual declaration
然而,我的签名实际上声明如下
module type SetS = sig
type 'a t
val empty : 'a t
val insert : 'a t -> 'a -> 'a t
val contains : 'a t -> 'a -> bool
val filter_map : ('a -> 'b option) -> 'a t -> 'b list
end
出于某种原因,我在编译时得到的错误显示了与我实际实现的不同的类型声明。为什么会发生这种情况,我该如何解决?
错误Signature mismatch
表示模块的派生签名与指定的签名不同。例如,假设我们要编写一个具有以下签名的模块,
module type Expected = sig
val filter : ('a -> bool) -> 'a list -> 'a list
end
然后我们写,
module Real : Expected = struct
let filter = List.filter_map
end
我们得到的错误信息是,
Signature mismatch:
Modules do not match:
sig val filter : 'a list -> f:('a -> 'b option) -> 'b list end
is not included in
Expected
Values do not match:
val filter : 'a list -> f:('a -> 'b option) -> 'b list
is not included in
val filter : ('a -> bool) -> 'a list -> 'a list
所以问题是我们提议的 filter
实现具有 'a list -> f:('a -> 'b option) -> 'b list
类型,但我们真正想要和期望的 filter
类型是 ('a -> bool) -> 'a list -> 'a list
。这就是错误消息所说的。
根据您的情况,您的实现具有推断类型 ('b -> 'b option) -> 'b t -> 'b list
,与所需类型 ('b -> 'a option) -> 'b t -> 'a list
不匹配。请注意,您的类型不太通用。它在不更改元素类型的情况下过滤列表。所以它只能过滤映射 int list
到 int list
,string list
到 string list
等等,不像更通用的实现能够映射 int list
到 string list
.
要纠正该问题,您需要仔细检查您的实施。确保您没有分支指令(如 if/then/else、匹配),这样一个分支 returns 输入列表的一个或多个元素,另一个分支 returns 一个或多个元素的输出列表。为了证明这一点,请考虑以下实现,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> xs
| Some x -> x :: filter_map f xs
这里我犯了一个错误,当 f x
的计算结果为 None
时,返回了输入列表 xs
。另一个分支,构建输出列表,所以我们统一了输入和输出列表的类型。在正确的实现中,你应该在两个分支中递归调用filter_map
,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> filter_map f xs
| Some x -> x :: filter_map f xs
当我尝试编译我的代码时,出现以下错误
Error: Signature mismatch:
...
Values do not match:
val filter_map : ('b -> 'b option) -> 'b t -> 'b list
is not included in
val filter_map : ('b -> 'a option) -> 'b t -> 'a list
File "set.ml", line 7, characters 2-55: Expected declaration
File "treeSet.ml", line 105, characters 10-20: Actual declaration
然而,我的签名实际上声明如下
module type SetS = sig
type 'a t
val empty : 'a t
val insert : 'a t -> 'a -> 'a t
val contains : 'a t -> 'a -> bool
val filter_map : ('a -> 'b option) -> 'a t -> 'b list
end
出于某种原因,我在编译时得到的错误显示了与我实际实现的不同的类型声明。为什么会发生这种情况,我该如何解决?
错误Signature mismatch
表示模块的派生签名与指定的签名不同。例如,假设我们要编写一个具有以下签名的模块,
module type Expected = sig
val filter : ('a -> bool) -> 'a list -> 'a list
end
然后我们写,
module Real : Expected = struct
let filter = List.filter_map
end
我们得到的错误信息是,
Signature mismatch:
Modules do not match:
sig val filter : 'a list -> f:('a -> 'b option) -> 'b list end
is not included in
Expected
Values do not match:
val filter : 'a list -> f:('a -> 'b option) -> 'b list
is not included in
val filter : ('a -> bool) -> 'a list -> 'a list
所以问题是我们提议的 filter
实现具有 'a list -> f:('a -> 'b option) -> 'b list
类型,但我们真正想要和期望的 filter
类型是 ('a -> bool) -> 'a list -> 'a list
。这就是错误消息所说的。
根据您的情况,您的实现具有推断类型 ('b -> 'b option) -> 'b t -> 'b list
,与所需类型 ('b -> 'a option) -> 'b t -> 'a list
不匹配。请注意,您的类型不太通用。它在不更改元素类型的情况下过滤列表。所以它只能过滤映射 int list
到 int list
,string list
到 string list
等等,不像更通用的实现能够映射 int list
到 string list
.
要纠正该问题,您需要仔细检查您的实施。确保您没有分支指令(如 if/then/else、匹配),这样一个分支 returns 输入列表的一个或多个元素,另一个分支 returns 一个或多个元素的输出列表。为了证明这一点,请考虑以下实现,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> xs
| Some x -> x :: filter_map f xs
这里我犯了一个错误,当 f x
的计算结果为 None
时,返回了输入列表 xs
。另一个分支,构建输出列表,所以我们统一了输入和输出列表的类型。在正确的实现中,你应该在两个分支中递归调用filter_map
,
let rec filter_map f = function
| [] -> []
| x :: xs -> match f x with
| None -> filter_map f xs
| Some x -> x :: filter_map f xs