我试图在OCaml中实现双端队列。这是我提出的代码(它在2个文件中 - 在queue.mli中的接口和在queue.ml中的实现)
module type QUEUE =
sig
type 'a queue
exception EmptyQueue
val empty : 'a queue
val is_empty : 'a queue -> bool
val push_front : 'a -> 'a queue -> 'a queue
val push_back : 'a -> 'a queue -> 'a queue
val remove_front : 'a queue -> ('a * 'a queue)
val remove_back : 'a queue -> ('a * 'a queue)
end;;
-
module Queue : QUEUE = struct
type 'a queue = {front : 'a list; back : 'a list; size : int}
exception EmptyQueue
let empty = {front = []; back = []; size = 0}
let is_empty q = if (q.front = [] && q.back = []) then true else false
let make_split l i =
let rec aux l nl i =
if i = 0 then
(List.rev nl, l) else
match l with
| [] -> failwith "Something went wrong"
| h :: t -> aux t (h :: nl) (i - 1)
in aux l [] i
let balance q =
if is_empty q then q else
if q.front = [] then
let iterator = (q.size / 2) in
let (qfront, qback) = make_split q.back iterator in
{front = qfront; back = qback; size = q.size} else
if q.back = [] then
let iterator = (q.size / 2) in
let (qback, qfront) = make_split q.front iterator in
{front = qfront; back = qback; size = q.size}
else q
let push_front e q =
let q1 = {front = e :: q.front; back = q.back; size = q.size + 1} in
balance q1
let push_back e q =
let q1 = {front = q.front; back = e :: q.back; size = q.size + 1} in
balance q1
let remove_front q =
if is_empty q then raise EmptyQueue else
if q.size = 1 then
match (q.front, q.back) with
| ([], h :: t) -> (h, empty)
| (h :: t, []) -> (h, empty)
| (_, _) -> failwith "Something went wrong"
else
let q1 = balance q in
let value = List.hd q1.front in
(value, {front = List.tl q1.front; back = q1.back; size = q.size - 1})
let remove_back q =
if is_empty q then raise EmptyQueue else
if q.size = 1 then
match (q.front, q.back) with
| ([], h :: t) -> (h, empty)
| (h :: t, []) -> (h, empty)
| (_, _) -> failwith "Something went wrong"
else
let q1 = balance q in
let value = List.hd q1.back in
(value, {front = q1.front; back = List.tl q1.back; size = q.size - 1})
end;;
问题是,它不会编译。尝试使用ocamlc -c queue.mli queue.ml
时,OCaml编译器会返回错误 - File "queue.ml", line 1, characters 15-20:
Error: Unbound module type QUEUE
。我无法理解为什么会这样,因为我在queue.mli中定义了类型QUEUE。那么,发生了什么?
答案 0 :(得分:2)
我认为问题在于您必须将queue.mli视为queue.ml的子集,而不是将其添加到queue.ml中。实际上,这意味着QUEUE的定义必须出现在queue.ml和queue.mli中。这种布局有一些优点,但它通常有点多余。