2017-12-06 9 views
0

Ich versuche, Modul/Schnittstelle (ich weiß nicht genau wie es heißt, ich bin neu in der Sprache) für grundlegende Operationen auf BST in OCaml. Mein Ziel ist es, eine Implementierung zu haben, die ich so etwas wie dies tun kann:BST mit Modulen - OCaml

T.create();; 
T.push(2);; 
T.push(3);; 
T.push(5);; 

um einen bst Baum von 2,3,5, bestehend zu bekommen.

Aber im Moment das ich so etwas wie dieses haben zu erreichen, schreiben:

let tee2 = T.push(2)(T.push(3)(T.push(5)(T.create())));; 
    T.postorder(tee2);; 

:

let teeBst = T.push(2)(T.push(3)(T.push(5)(T.create())));; 

Also, wenn ich bin Überprüfung/mit meinem Code ich es so zu tun haben der Ausgang ist in Ordnung:

# val tee2 : T.bt = <abstr> 
# - : int list = [2; 3; 5] 

Aber, wie ich schon sagte, würde ich mag diese, wie unten erreichen tun:

T.push(2);; 
T.push(3);; 
T.push(5);; 
T.postorder();; 

(Ich weiß, das einige Änderungen an meinem Postorder-Funktion erfordert aber die, die ich bin derzeit mit ist eine temporäre, so kann ich den Baum prüfe ich atm haben)

Unten ist meine Implementierung. Wenn Sie die Lösung zu sehen, lassen Sie es mich wissen;)

module type Tree = 
    sig 
     type bt 
     val create: unit -> bt 
     val push: int -> bt -> bt 
     val find: int -> bt -> bool 
     val preorder: bt -> int list 
     val postorder: bt -> int list 
     val inorder: bt -> int list 
    end;; 

module T : Tree = 
    struct 
     type bt = E | B of bt * int * bt 
     let create() = E 
     let rec push x = function 
      | E -> B(E, x, E) 
      | B (l, y, r) when x<y -> B(push x l, y, r) 
      | B (l, y, r) when x>y -> B(l, y, push x r) 
      | xs -> xs;; 

     let rec find x = function 
      | E -> false 
      | B(l, y,_) when x< y -> find x l 
      | B(_,y,r) when x>y -> find x r 
      | _ -> true;; 

     let rec preorder = function 
      | B(l,v,r) -> v::(preorder r) @ (preorder l) 
      | E -> [];; 

     let rec inorder = function 
      | B(l,v,r) ->(inorder r) @ v::(inorder l) 
      | E -> [] 


     let rec postorder = function 
      | B(l,v,r) -> (postorder r) @ (postorder l) @ [v] 
      | E -> [] 
    end;; 

Antwort

1

Es scheint, wie Sie Module wollen Klassen sein, aber ich würde raten Sie mehr idiomatische Lösungen zu berücksichtigen. Haben Sie überlegt, den Pfahlbetreiber zu benutzen?

T.create() 
|> T.push(2) 
|> T.push(3) 
|> T.push(5) 
|> T.postorder;; 

Oder mit lokalen offen (was mehr Sinn macht, wenn Sie ein Modul mit einem längeren Namen haben als nur T natürlich) können Sie sogar

T.(
    create() 
    |> push(2) 
    |> push(3) 
    |> push(5) 
    |> postorder 
); 

tun, was Sie fragen für müssten Einführung eines globalen veränderlichen Zustands, der nicht nur "einige Veränderungen", sondern ein völlig anderes Paradigma darstellt. Und eines, das allgemein verpönt ist, weil es Ihren Code unvorhersehbar macht und schwer zu debuggen ist, da es sich auf einen Zustand stützt, der sich von irgendwoher jederzeit ändern kann.

Eine andere Möglichkeit ist es, Klassen zu verwenden, da OCam diese auch hat. Dann hättest du immer noch einen veränderlichen Zustand, aber es wäre zumindest enthalten.

+0

Vielen Dank! Rohrbetreiber waren das, wonach ich suchte. Aber jetzt habe ich ein Problem mit der Postorder-Funktion. Ist es möglich, diese Funktion auf "unit-> int list" zu setzen, anstatt auf das, was ich jetzt habe, "bt -> int list", weil ich scheinbar keinen Weg finde, was bedeutet, dass ich |> T. postorder nicht verwenden kann() – hdw3

+1

Die von Ihnen verwendete Funktionssyntax ist irreführend. OCaml verwendet keine Klammern für die Funktionsanwendung, und der Grund, warum es mit einem einzigen Argument funktioniert, ist rein zufällig. Die richtige Syntax lautet 'T.create() |> T.push 2 |> T. postorder'. Sie können ein einzelnes Argument in runde Klammern setzen und den Leerraum zwischen der Funktion und dem geklammerten Argument entfernen, aber es dient nur der Verwirrung. – glennsl