[英]Implementing Okasaki's bootstrapped heaps in OCaml, why doesn't it compile?
(A minimal non-compiling example can be found at https://gist.github.com/4044467 , see more background below.) (一个最小的非编译示例可以在https://gist.github.com/4044467上找到,请参阅下面的更多背景。)
I am trying to implement Bootstrapped Heaps introduced in Chapter 10 of Okasaki's Purely Functional Data Structure . 我正在尝试实现Okasaki的Pure Functional Data Structure第10章中介绍的Bootstrapped堆 。 The following is a simplified version of my non-compiling code.
以下是我的非编译代码的简化版本。
We're to implement a heap with following signature: 我们将使用以下签名实现堆:
module type ORDERED =
sig
type t
val compare : t -> t -> int
end
module type HEAP =
sig
module Elem : ORDERED
type heap
val empty : heap
val insert : Elem.t -> heap -> heap
val find_min : heap -> Elem.t
val delete_min : heap -> heap
end
We say a data structure is bootstrapped when its implementation depends on another implementation of the same kind of data structure. 我们说一个数据结构的实现依赖于相同类型数据结构的另一个实现而被引导 。 So we have a heap like this (the actual implementation is not important):
因此,我们有一个这样的堆(实际的实现并不重要):
module SomeHeap (Element : ORDERED) : (HEAP with module Elem = Element) =
struct
module Elem = Element
type heap
let empty = failwith "skipped"
let insert = failwith "skipped"
let find_min = failwith "skipped"
let delete_min = failwith "skipped"
end
Then, the bootstrapped heap we're going to implement, which can depend on any heap implementation, is supposed to have the following signature: 然后,我们将要实现的自举堆(可能依赖于任何堆实现)应该具有以下签名:
module BootstrappedHeap
(MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
(Element : ORDERED) : (HEAP with module Elem = Element)
So we can use it like this: 因此我们可以像这样使用它:
module StringHeap = BootstrappedHeap(SomeHeap)(String)
The implementation of BootstrappedHeap, according to Okasaki, is like this: 冈崎说,BootstrappedHeap的实现是这样的:
module BootstrappedHeap
(MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
(Element : ORDERED) : (HEAP with module Elem = Element) =
struct
module Elem = Element
module rec BootstrappedElem :
sig
type t =
| E
| H of Elem.t * PrimH.heap
val compare : t -> t -> int
end =
struct
type t =
| E
| H of Elem.t * PrimH.heap
let compare t1 t2 = match t1, t2 with
| H (x, _), H (y, _) -> Elem.compare x y
| _ -> failwith "unreachable"
end
and PrimH : (HEAP with module Elem = BootstrappedElem) =
MakeH(BootstrappedElem)
type heap
let empty = failwith "not implemented"
let insert = failwith "not implemented"
let find_min = failwith "not implemented"
let delete_min = failwith "not implemented"
end
But this is not compiling! 但这还没有编译! The error message is:
错误消息是:
File "ordered.ml", line 52, characters 15-55:
Error: In this `with' constraint, the new definition of Elem
does not match its original definition in the constrained signature:
Modules do not match:
sig type t = BootstrappedElem.t end
is not included in
ORDERED
The field `compare' is required but not provided
The line 52 is the line 52行是
and PrimH : (HEAP with module Elem = BootstrappedElem) =
I think BootstrappedElem
did implement ORDERED
as it has both t
and compare
, but I failed to see why the compiler fails to find the compare
function. 我认为
BootstrappedElem
确实实现了ORDERED
因为它同时具有t
和compare
,但是我看不到为什么编译器无法找到compare
函数。
Change the signature of BootstrappedElem to 将BootstrappedElem的签名更改为
module rec BootstrappedElem : ORDERED
will make it compiling but this will hide the type constructor E
and T
in BootstrappedElem
to make it impossible to implement the later parts. 将对其进行编译,但这将在
BootstrappedElem
隐藏类型构造函数E
和T
,以致于无法实现后面的部分。
The whole non-compiling code can be downloaded at https://raw.github.com/gist/4044281/0ce0336c40b277e59cece43dbadb9b94ce6efdaf/ordered.ml 整个非编译代码可以从https://raw.github.com/gist/4044281/0ce0336c40b277e59cece43dbadb9b94ce6efdaf/ordered.ml下载
I believe this might be a bug in the type-checker. 我相信这可能是类型检查器中的错误。 I have reduced your code to the following example:
我已将您的代码简化为以下示例:
module type ORDERED =
sig
type t
val compare : t -> t -> int
end
module type CARRY = sig
module M : ORDERED
end
(* works *)
module HigherOrderFunctor
(Make : functor (X : ORDERED) -> (CARRY with module M = X))
= struct
module rec Base
: (ORDERED with type t = string)
= String
and Other
: (CARRY with module M = Base)
= Make(Base)
end
(* does not work *)
module HigherOrderFunctor
(Make : functor (X : ORDERED) -> (CARRY with module M = X))
= struct
module rec Base
: sig
(* 'compare' seems dropped from this signature *)
type t = string
val compare : t -> t -> int
end
= String
and Other
: (CARRY with module M = (Base : sig type t = string val compare : t -> t -> int end))
= Make(Base)
end
I don't understand why the first code works and the second (which seems equivalent) doesn't. 我不明白为什么第一个代码有效而第二个代码(看来等效)为什么不起作用。 I suggest you wait a bit to see if an expert comes with an explanation (Andreas?), then consider sending a bug report .
我建议您稍等一下,看看专家是否提供了解释(Andreas?),然后考虑发送错误报告 。
In this case, a solution is to first bind the signature that seems mishandled: 在这种情况下,一种解决方案是首先绑定似乎处理不当的签名:
(* works again *)
module HigherOrderFunctor
(Make : functor (X : ORDERED) -> (CARRY with module M = X))
= struct
(* bind the problematic signature first *)
module type S = sig
type t = string
val compare : t -> t -> int
end
module rec Base : S = String
and Other : (CARRY with module M = Base) = Make(Base)
end
However, that is not possible in your setting, because the signature of BootstrappedElem
is mutually recursive with BootstrappedHeap
. 但是,这是不可能在你的设置,因为签名
BootstrappedElem
是相互递归BootstrappedHeap
。
A workaround is to avoid the apparently-delicate with module ...
construct and replace it with a simple type equality with type Elem.t = ...
: 一种解决方法是避免使用明显的
with module ...
构造并将其替换with type Elem.t = ...
的简单类型相等:
module BootstrappedHeap
(MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
(Element : ORDERED) : (HEAP with module Elem = Element) =
struct
module Elem = Element
module rec BootstrappedElem :
sig
type t =
| E
| H of Elem.t * PrimH.heap
val compare : t -> t -> int
end =
struct
type t =
| E
| H of Elem.t * PrimH.heap
let compare t1 t2 = match t1, t2 with
| H (x, _), H (y, _) -> Elem.compare x y
| _ -> failwith "unreachable"
end
and PrimH : (HEAP with type Elem.t = BootstrappedElem.t) =
MakeH(BootstrappedElem)
type heap
let empty = failwith "not implemented"
let insert = failwith "not implemented"
let find_min = failwith "not implemented"
let delete_min = failwith "not implemented"
end
You could also avoid the mutual recursion and define both BootstrappedElem
and BootstrappedHeap
in one recursive knot, by defining BootstrappedElem
inside the recursive BootstrappedHeap
. 您也可避免相互递归和定义都
BootstrappedElem
和BootstrappedHeap
在一个递归结,通过定义BootstrappedElem
递归内 BootstrappedHeap
。
module BootstrappedHeap
(MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
(Element : ORDERED) : (HEAP with module Elem = Element) =
struct
module rec BootstrappedHeap : sig
module Elem : sig
type t = E | H of Element.t * BootstrappedHeap.heap
val compare : t -> t -> int
end
include (HEAP with module Elem := Elem)
end = struct
module Elem = struct
type t = E | H of Element.t * BootstrappedHeap.heap
let compare t1 t2 = match t1, t2 with
| H (x, _), H (y, _) -> Element.compare x y
| _ -> failwith "unreachable"
end
include (MakeH(Elem) : HEAP with module Elem := Elem)
end
module Elem = Element
type heap
let empty = failwith "not implemented"
let insert = failwith "not implemented"
let find_min = failwith "not implemented"
let delete_min = failwith "not implemented"
end
This style corresponds naturally to your decision of embedding Elem
in the HEAP
signature and using with module ...
for refinement. 这种风格自然符合您决定将
Elem
嵌入HEAP
签名并with module ...
使用with module ...
进行优化的决定。 Another solution would have been to define HEAP
as a functor returning a signature, used as HEAP(Elem).S
, and I suppose a different recursive style could have been chosed. 另一个解决方案是将
HEAP
定义为返回签名的函子,用作HEAP(Elem).S
,我想可以选择其他递归样式。 Not to say that this would have been better: I think the "abstract module" style is more convenient. 并不是说这样做会更好:我认为“抽象模块”样式更方便。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.