15

En Leroy's paper sobre cómo los módulos recursiva se escriben en OCaml, está escrito que los módulos se comprueban en un entorno hecho de aproximaciones de los tipos de módulos:escribiendo módulos recursivas

module rec A = ... and B = ... and C = ... 

Un entorno {A -> aprox (A); B -> aproximadamente (B); C -> approx (C)} primero se construye, y luego se usa para calcular los tipos de A, B y C.

Me di cuenta de que, en algunos casos, las aproximaciones no son lo suficientemente buenas y la comprobación de tipos falla. En particular, cuando se colocan fuentes de unidades de compilación en una definición de módulo recursivo, la comprobación de tipo puede fallar, mientras que el compilador pudo compilar las unidades de compilación por separado.

Volviendo a mi primer ejemplo, encontré que una solución sería escribir A en el entorno aproximado inicial, pero luego escribir B en ese entorno inicial extendido con el nuevo tipo calculado de A, y escribir C en el env anterior con el nuevo tipo computado de B, y así sucesivamente.

Antes de investigar más, me gustaría saber si hay algún trabajo previo sobre este tema, mostrando que dicho esquema de compilación para módulos recursivos es seguro o inseguro? ¿Hay un contraejemplo que muestre un programa inseguro correctamente escrito con este esquema?

+0

Una pregunta muy interesante, de hecho. Tenga en cuenta que su solución propuesta ignora que el tipo de A puede depender de la de B y C, si no fuera así, no habría ninguna razón para escribirlos juntos (a diferencia de la orden de dependencia). – Ingo

+1

No, en realidad, el tipo de A puede depender de B y C, pero supongo que la aproximación de B y C es suficiente en ese caso.Mi pregunta proviene de un ejemplo real, lo resolví escribiendo un parche con esta solución en el compilador, y el programa era seguro (porque estaba compuesto por unidades de compilación con tipos recursivos), pero quiero saber si el parche está seguro en el compilador. caso general. –

Respuesta

16

En primer lugar, tenga en cuenta que Leroy (o Ocaml) no permite module rec sin anotaciones de firma explícitas. Así que es más bien

module rec A : SA = ... and B : SB = ... and C : SC = ... 

y el medio ambiente es aproximativo {R: aprox (SA), B: aprox (SB), C: aprox (SC)}.

No es sorprendente que algunos módulos comprueben el tipo cuando se definen por separado, pero no cuando se definen recursivamente. Después de todo, lo mismo ya es cierto para las declaraciones de lenguaje central: en un 'let rec', las ocurrencias recursivas de las variables vinculadas son monomórficas, mientras que con las declaraciones separadas 'let', puede usar las variables previas polimórficamente. Intuitivamente, la razón es que no puede tener todo el conocimiento que necesitaría para inferir los tipos más liberales antes de que realmente haya verificado las definiciones.

Respecto a su sugerencia, el problema es que hace que la construcción module rec sea asimétrica, es decir, el orden sería importante en formas potencialmente sutiles. Eso viola el espíritu de las definiciones recursivas (al menos en ML), que siempre debe ser indiferente al orden.

En general, el problema con el tipado recursivo no es tanto la solidez, sino más bien la integridad. No desea un sistema de tipo que sea indecidible en general, o cuya especificación dependa de artefactos algorítmicos (como verificar el orden).

En una nota más general, es bien sabido que el tratamiento de Ocaml de los módulos recursivos es bastante restrictivo. Ha habido trabajo, p. por Nakata & Garrigue, que lleva sus límites más allá. Sin embargo, estoy convencido de que, en última instancia, no podrá ser tan liberal como desee (y eso se aplica también a otros aspectos de su sistema de módulos de tipo, por ejemplo, funtores) sin abandonar el enfoque puramente sintáctico de Ocaml para el tipado de módulos. . Pero entonces, soy parcial. :)

+0

Gracias por el puntero al trabajo de Nakata & Garrigue, no sabía nada al respecto. Es cierto que el orden no importa para 'let rec', pero sí importa en otra parte del lenguaje' let x = x + 2 en let x = x * 3 in ... 'depende del orden. Entonces, ¿por qué no introducir un 'módulo incremental rec 'donde el orden sería importante, y permitir el tipeo de programas que no son tipables ahora? (ahora, debo leer el documento ...) –

+0

Bueno, un 'let' anidado no es del todo comparable. Podría comparar con un paralelo 'let x = a y y = b in ...', donde de hecho, el orden no importa para tipear. ¿Por qué no hay 'rec incremental '? Bueno, en mi humilde opinión, sería un hack feo, y uno que solo cubre algunos casos de uso específico de todos modos. ;) ¿No prefieres una solución más general? –

+0

Me gustaría una solución más general, pero cuando no la hay (todavía necesito leer más sobre módulos recursivos ...), me siento cómodo con una solución hackish. Y no creo que sea para "algunos casos de uso específicos", creo que mi problema podría aparecer con bastante frecuencia. –