2011-01-20 10 views
9

Al utilizar definiciones de módulos mutuamente recursivas en OCaml, es necesario dar firmas, incluso en el archivo .ml. Esto es una molestia en la que también quiero exponer una interfaz determinada del .mli, ya que termino repitiendo la firma dos veces. :(!¿Por qué el requisito de firmas en módulos mutuamente recursivos en OCaml?

module rec Client : sig 
    type ('serv,'cli) t 

    (* functions ... *) 
end = struct 
    type ('serv,'cli) t = 
    { server: ('serv,'cli) Server.t 
    ; (* other members ... *) 
    } 
end 
and Server : sig 
    type ('serv,'cli) t 

    (* functions ... *) 
end = struct 
    type ('serv,'cli) t = 
    { mutable clients: ('serv,'cli) Client.t list 
    ; mutable state: 'serv 
    } 

    (* functions again ... *) 
end 

Ésta es una aproximación de lo que estoy haciendo (Client objetos de tipo conocen la Server que les instancia. Server s conocen sus Client s).

Por supuesto, las firmas son . repetida en el .mli ¿por qué es necesario

. (Nota: no me quejo, pero en realidad quiero saber si hay un tipo de teoría o "difícil problema del compilador" -relacionado razón para esto)?

Respuesta

4

Mi suposición: para compilar los módulos recursivos, el compilador necesita anotaciones tipo para la implementación. En el archivo mli (si está utilizando alguno), los tipos de esos módulos pueden restringirse u ocultarse aún más, de modo que, en general, no es razonable que el compilador espere encontrar tipos útiles en mli wrt resolviendo type-recursión.

+0

Eso tiene sentido. De hecho, hago uso de esta "característica" al exponer una firma de tipo diferente para consumidores externos en el '.mli'; Debería haberme dado cuenta. – Ashe

+1

Buena conjetura. Las anotaciones de tipo son obligatorias porque la inferencia en el caso de módulos recíprocos y funtores es indecidible en general. La literatura está llena de intentos de perfeccionar los sistemas de tipo para optimizar los requisitos mínimos de anotación y conservar la solidez. Si el sistema de tipo de OCaml podría mejorarse para reducir la carga de requisitos de anotación es discutible. –

7

Por lo que yo sé, no hay forma de evitar esto. En un nivel muy alto, en lo que respecta al compilador, la firma de tipo del Cliente está incompleta hasta que conoce la firma de tipo del Servidor, y viceversa. En principio, hay una forma de evitar esto: el compilador podría hacer una referencia cruzada de sus archivos .mli en tiempo de compilación. Pero ese enfoque tiene desventajas: mezcla algunas de las responsabilidades del compilador y del enlazador, y hace que la compilación modular (sin juego de palabras) sea más difícil.

Si está interesado, le recomiendo el original proposal de Xavier Leroy para módulos recursivos.

+0

¡Gracias por el enlace! La teoría de tipos está un poco por encima de mí, pero sigue siendo una buena lectura. Pero supongo que como mencionó Ygrek, no es para que el .mli declare el tipo utilizado en la compilación del módulo mismo. Sería más feo, como mencionas, si intentara hacerlo. – Ashe