2012-04-03 17 views
10

Soy bastante nuevo con OCaml Module y no he podido utilizar mi propio módulo sin combinar tanto un "incluir" como un "abrir". He intentado poner la firma en un archivo .mli separado, sin éxito.OCaml Module: incluir AND open?

A continuación me indicaron un mínimo (no) ejemplo de trabajo, que estoy tratando de compilar con

ocamlc -o main Robot.ml main.ml 

Lo que tengo que hacer sólo para tener que usar "abrir" o sólo " incluir ", pero no ambos?


Archivo "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 

Archivo "main.ml" (no funciona):

open Robot;; 

top(); 

Archivo "main.ml" (de trabajo):

include Robot;; 
open Robot;; 

top(); 
+0

Creo que tiene respuestas a sus preguntas. También es posible que desee leer sobre [unidades de compilación] (http://caml.inria.fr/pub/docs/manual-ocaml/manual020.html). Pero por favor una vez que haya entendido lo que 'abierto 'hace. No lo use, hace que sea mucho más difícil entender su código. –

+0

Bueno, normalmente estaría de acuerdo, pero en ese caso el objetivo es proporcionar una simple "biblioteca de robots" para enseñar programación básica a principiantes (en particular, pero sin limitarse a OCaml). Así que preferiría evitar la sintaxis de Robot.top(), tanto como sea posible. –

+0

Bueno, creo que realmente haría que fuera mucho más fácil de entender para los principiantes renderizar explícitamente el objeto sobre el que actúan. De todos modos, es posible que desee echar un vistazo a la documentación de [abrir] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd170) y [incluir] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd171). –

Respuesta

11

Tienes dos niveles de Robot. Como llamó explícitamente a su módulo "Robot" dentro del archivo robot.ml, necesitará abrir Robot y luego llamar a Robot.top(). Cualquier cosa en el archivo robot.ml ya está implícitamente dentro de un módulo Robot.

Puede deshacerse de la declaración adicional 'módulo Robot' en robot.ml.

robot.ml se convertiría en:

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


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

entonces debería funcionar como lo tienes en tu main.ml.

Actualización basada en comentarios a continuación: Si está preocupado de que todo en robot.ml ahora será visible cuando se abra 'Robot' se puede definir un archivo robot.mli que especifica las funciones que están disponibles externamente. Por ejemplo, digamos que se agrega una función llamada ayudante en robot.ml:

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

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

... y luego definiría su robot.mli de la siguiente manera:

val top: unit -> unit 

Entonces digamos que usted intenta llamar a ayudante desde main.ml:

open Robot;; 

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

Luego, cuando intenta compilar obtendrá un error:

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

De hecho, pero ahora la firma no tiene efecto, ya que todo es visible desde la principal. Entendí los "dos niveles de Robot" pero no tenía idea de cómo solucionarlo manteniendo una firma útil. –

+0

Si desea asegurarse de que solo dentro del módulo Robot esté visible en main, defina un archivo robot.mli que solo exporte lo que desea exportar (voy a editar mi respuesta anterior para mostrar esto). – aneccodeal

5

tienes dos maneras de hacer esto:

  • En primer lugar, puede restringir su subestructura para que sea de la firma correcta:

    module Robot : RobotSignature = struct ... end 
    

    Luego, en main.ml, se puede hacer open Robot.Robot: la primera Robot significa que la unidad de compilación asociada a robot.ml, la segunda Robot es el submódulo que ha definido el interior robot.ml

  • También puede eliminar de una sola planta y crear robot.mli que contiene:

    val top: unit -> unit 
    

    y robot.ml que contiene:

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

    Puede compilar los módulos usando y luego en main.ml simplemente use open Robot.

+0

O mejor, no 'abra Robot', pero llame a' Robot.top() '. –

+0

y si '' 'Robot.Robot.top' '' es demasiado largo para uso frecuente, escriba '' 'let module R = Robot.Robot en R.top' '' – lambdapower