Functional programming 队列实现中的未绑定模块类型

Functional programming 队列实现中的未绑定模块类型,functional-programming,ocaml,Functional Programming,Ocaml,我试图在OCaml中实现双端队列。下面是我提出的一个代码(在2个文件中—queue.mli中的接口和queue.ml中的实现) - 问题是,它无法编译。尝试使用ocamlc-c queue.mli queue.ml时OCaml编译器返回一个错误-文件“queue.ml”,第1行,字符15-20: 错误:未绑定模块类型队列。我不明白为什么会这样,因为我在QUEUE.mli中定义了类型QUEUE。那么,到底发生了什么?我认为问题在于,您必须将queue.mli视为queue.ml的子集,而不是添加到

我试图在OCaml中实现双端队列。下面是我提出的一个代码(在2个文件中—queue.mli中的接口和queue.ml中的实现)

-

问题是,它无法编译。尝试使用
ocamlc-c queue.mli queue.ml时
OCaml编译器返回一个错误-
文件“queue.ml”,第1行,字符15-20:

错误:未绑定模块类型队列
。我不明白为什么会这样,因为我在QUEUE.mli中定义了类型QUEUE。那么,到底发生了什么?

我认为问题在于,您必须将queue.mli视为queue.ml的子集,而不是添加到queue.ml中的内容。实际上,这意味着队列的定义必须出现在QUEUE.ml和QUEUE.mli中。这种布局有很多优点,但通常有点多余。

您也可以在单独的文件中定义模块类型,这样可以避免重复
s.mli
似乎是这个文件的传统名称(当然,如果您正在创建库,打包是为了避免冲突)。
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;;