2014-11-26 3 views
1

OCaml에서 양방향 큐를 구현하려고합니다.큐에 언 바운드 모듈 유형 구현

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;; 

- 여기에 내가 (queue.ml에서 queue.mli의 인터페이스와 구현이이 개 파일에 있어요) - 내놓았다 코드가

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 유형을 정의했는지 알 수 없습니다. 그래서, 무슨 일이 일어나고있는거야?

답변

1

저는 문제는 queue.mli를 queue.ml의 하위 집합으로 생각해야한다는 것입니다. queue.ml에 추가되는 내용이 아니라 문제입니다. 실제로 이것은 QUEUE의 정의가 queue.mli뿐만 아니라 queue.ml에 나타나야한다는 것을 의미합니다. 이 레이아웃에는 이점이 있지만 종종 약간 중복됩니다.

+1

또한 모듈 유형을 별도의 파일로 정의 할 수 있으므로 중복을 피할 수 있습니다. 's.mli'는이 파일의 전통적인 이름 인 것 같습니다. 물론 라이브러리를 만들면 충돌을 피할 수 있습니다. –