2012-04-03 19 views
10

Sono abbastanza nuovo con OCaml Module e non sono riuscito a utilizzare il mio modulo senza combinare sia un "include" che un "aperto". Ho provato a mettere la firma in un file .mli separato, senza successo.Modulo OCaml: include E aperto?

Qui di seguito ho indicato un minimo (non) esempio di lavoro, che sto cercando di compilare con

ocamlc -o main Robot.ml main.ml 

Cosa devo fare per avere solo usare "aperto", oppure solo " includere ", ma non entrambi?


File "Robot.ml":

module type RobotSignature = 
sig 
    val top: unit -> unit 
end 

module Robot = 
struct 
    let top() = 
     begin 
     Printf.printf "top\n" 
     end 
    (* Should not be visible from the 'main' *) 
    let dummy() = 
     begin 
     Printf.printf "dummy\n" 
     end 
end 

File "main.ml" (non funzionante):

open Robot;; 

top(); 

File "main.ml" (di lavoro):

include Robot;; 
open Robot;; 

top(); 
+0

Penso che tu abbia le risposte alle tue domande. Si consiglia inoltre di leggere su [unità di compilazione] (http://caml.inria.fr/pub/docs/manual-ocaml/manual020.html). Ma per favore, una volta che hai capito cosa fa "open". Non usarlo, rende più difficile la comprensione del tuo codice. –

+0

Beh, di norma sarei d'accordo, ma in questo caso l'obiettivo è fornire una semplice "biblioteca di robot" per insegnare la programmazione di base ai principianti (in particolare, ma non solo, OCaml). Quindi preferirei evitare la sintassi Robot.top(), il più possibile. –

+0

Beh, penso che in effetti sarebbe molto più sottostimabile per i principianti rendere esplicito l'oggetto su cui agiscono. Ad ogni modo potresti anche voler dare un'occhiata alla documentazione di [open] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd170) e [include] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd171). –

risposta

11

Hai due livelli di Robot. Dal momento che hai chiamato il tuo modulo "Robot" nel file robot.ml, dovrai aprire Robot e chiamare Robot.top(). Qualsiasi cosa nel file robot.ml è già inserita implicitamente all'interno di un modulo Robot.

Si potrebbe sbarazzarsi della dichiarazione aggiuntiva "modulo Robot" in robot.ml.

robot.ml sarebbe diventato:

module type RobotSignature = 
sig 
    val top: unit -> unit 
end 


let top() = 
    begin 
     Printf.printf "top\n" 
    end 

allora dovrebbe funzionare come lo avete nel vostro main.ml.

Aggiornamento basato sul commento seguente: Se si è preoccupati che tutto in robot.ml sarà ora visibile quando si apre Robot, è possibile definire un file robot.mli che specifica le funzioni che sono disponibili esternamente. Per esempio, diciamo che si aggiunge una funzione chiamata aiutante in robot.ml:

let top() = 
    begin 
    Printf.printf "top\n" 
    end 

let helper() = 
    Printf.printf "helper\n" 

... e poi definire la vostra robot.mli come segue:

val top: unit -> unit 

Quindi diciamo che si prova a chiamare l'helper dal main.ml:

open Robot;; 

top(); 
(* helper will not be visible here and you'll get a compile error*) 
helper() 

Poi, quando si tenta di compilare si otterrà un errore:

$ ocamlc -o main robot.mli robot.ml main.ml 
File "main.ml", line 4, characters 0-6: 
Error: Unbound value helper 
+0

In effetti ma ora la firma non ha effetto poiché tutto è visibile dal principale. Ho capito i "due livelli di Robot" ma non avevo idea di come sistemarlo mantenendo una firma utile. –

+0

Se si desidera garantire che solo quello all'interno del modulo Robot sia visibile all'interno del main, quindi definire un file robot.mli che esporta solo ciò che si desidera esportare (modificherò la mia risposta sopra per mostrarlo). – aneccodeal

5

ci sono due modi per farlo:

  • In primo luogo, è possibile vincolare la tua sottostruttura per essere della firma giusta:

    module Robot : RobotSignature = struct ... end 
    

    Poi, nel main.ml, si può fare open Robot.Robot: il primo Robot significa che l'unità di compilazione associata al robot.ml, il secondo Robot è il modulo è stato definito all'interno robot.ml

  • È inoltre possibile rimuovere un unico livello e creare robot.mli contenente:

    val top: unit -> unit 
    

    e robot.ml contenente:

    let top() = 
        Printf.printf "top\n" 
    
    (* Should not be visible from the 'main' *) 
    let dummy() = 
        Printf.printf "dummy\n" 
    

    È possibile compilare i moduli utilizzando e quindi in main.ml è sufficiente utilizzare open Robot.

+0

O meglio non 'apri Robot' ma chiama' Robot.top() '. –

+0

e se '' 'Robot.Robot.top' '' è troppo lungo per un utilizzo frequente, scrivi '' 'lascia il modulo R = Robot.Robot in R.top' '' – lambdapower