He estado programando durante varios años, pero no estoy muy familiarizado con el CS teórico. Recientemente he estado tratando de estudiar lenguajes de programación y, como parte de eso, la verificación de tipos y la inferencia.
Mi pregunta es, si trato de escribir una inferencia de tipos y un programa de verificación para un lenguaje de programación, y deseo probar que mi typechecker funciona, ¿cuál es exactamente la prueba que estoy buscando?
En lenguaje sencillo, quiero que mi verificador de tipos pueda identificar cualquier error en un fragmento de código que pueda ocurrir en tiempo de ejecución. Si tuviera que usar algo como Coq para probar que mi implementación es correcta, ¿qué intentará mostrar exactamente esta "prueba de corrección"?
fuente
2 + "hello"
ese están 'atascados'). Una vez formalizado esto, puede probar el teorema de solidez de tipo. Eso significa que ningún programa tipificable puede evolucionar a un error de tipo inmediato. Formalmente, demuestra que si un programa es tipificable y para cualquier n ≥ : si M ejecuta n pasos para convertirse en N , entonces N no tiene un error de tipo inmediato. (1/2)Respuestas:
La pregunta se puede interpretar de dos maneras:
La primera es realmente una pregunta en la verificación del programa y tiene poco que ver con la escritura. Solo necesita mostrar que su implementación cumple con sus especificaciones, vea la respuesta de Andrej.
Déjame hablar sobre la pregunta posterior. Como dijo Andrej, desde un punto de vista abstracto, un sistema de mecanografía parece imponer propiedades en los programas. En la práctica, su sistema de escritura busca evitar que ocurran errores, lo que significa que los programas que se pueden escribir no deben exhibir la clase de errores de interés. Para demostrar que T hace lo que crees que debería hacer, debes hacer dos cosas.T T
Primero, usted define formalmente lo que significa que un programa tenga un error de escritura inmediato . Hay muchas formas en que esto se puede definir, depende de usted. Por lo general, queremos evitar programas como
2 + "hello"
. En otras palabras, debe definir un subconjunto de programas, llámelos Malo , que contiene exactamente los programas con un error de escritura inmediato.Cómo probar este teorema depende de los detalles del idioma, el sistema de escritura y la elección de Bad .
Tenga en cuenta que no todos los sistemas de mecanografía tienen "reducción de sujeto", por ejemplo, tipos de sesión. En este caso, se requieren técnicas de prueba más sofisticadas.
fuente
¡Buena pregunta! Pregunta qué esperamos de los tipos en un idioma escrito.
Primero tenga en cuenta que podemos escribir cualquier lenguaje de programación con la unidad : simplemente elija una letra, diga
U
y diga que cada programa tiene tipoU
. Esto no es terriblemente útil, pero tiene sentido.int
No hay fin a lo expresivos que pueden ser sus tipos. En principio, podrían ser cualquier tipo de enunciados lógicos, podrían usar la teoría de categorías y otras cosas, etc. Por ejemplo, los tipos dependientes le permitirán expresar cosas como "esta función asigna listas a listas para que la salida sea una entrada ordenada". Puede ir más allá, en este momento estoy escuchando una charla sobre "lógicas de separación concurrente" que le permite hablar sobre cómo funcionan los programas concurrentes con estado compartido. Cosas lujosas.
El arte de los tipos en el diseño del lenguaje de programación es uno de equilibrar la expresividad y la simplicidad :
La simplicidad no debe subestimarse, ya que no todos los programadores tienen un doctorado en teoría de lenguajes de programación.
Así que volvamos a su pregunta: ¿cómo sabe que su sistema de tipos es bueno ? Bueno, pruebe los teoremas que muestran que sus tipos están equilibrados. Habrá dos tipos de teoremas:
Teoremas que dicen que tus tipos son útiles . Saber que un programa tiene un tipo debería implicar algunas garantías, por ejemplo, que el programa no se atascará (eso sería un teorema de seguridad ). Otra familia de teoremas conectaría los tipos con los modelos semánticos para que podamos comenzar a usar matemáticas reales para probar cosas sobre nuestros programas (esos serían los teoremas de adecuación y muchos otros). La unidad anterior es mala porque no tiene teoremas tan útiles.
Teoremas que dicen que tus tipos son simples . Uno básico sería que es decidible si una expresión dada tiene un tipo dado. Otra característica de simplicidad es dar un algoritmo para inferir un tipo. Otros teoremas sobre la simplicidad serían: que una expresión tiene como máximo un tipo, o que una expresión tiene un tipo principal (es decir, el "mejor" entre todos los tipos que tiene).
Es difícil ser más específico porque los tipos son un mecanismo muy general. Pero espero que veas a qué debes disparar. Como la mayoría de los aspectos del diseño del lenguaje de programación, no existe una medida absoluta de éxito. En cambio, hay un espacio de posibilidades de diseño, y lo importante es comprender en qué parte del espacio se encuentra o quiere estar.
fuente
Hay algunas cosas diferentes a las que podría referirse con "demostrar que mi typechecker funciona". Lo cual, supongo, es parte de lo que hace tu pregunta;)
La mitad de esta pregunta está demostrando que su teoría de tipos es lo suficientemente buena como para probar las propiedades del lenguaje. La respuesta de Andrej aborda esta área muy bien. La otra mitad de la pregunta es, suponiendo que el lenguaje y su sistema de tipos ya estén fijos, ¿cómo puede probar que su verificador de tipos en particular implementa el sistema de tipos correctamente? Hay dos perspectivas principales que puedo ver aquí.
Una es: ¿cómo podemos confiar en que alguna implementación en particular coincida con sus especificaciones? Dependiendo del grado de garantías que desee, es posible que esté satisfecho con un gran conjunto de pruebas, o puede que desee algún tipo de verificación formal, o más probablemente una combinación de ambos . La ventaja de esta perspectiva es que realmente resalta la importancia de establecer límites en las afirmaciones que está haciendo: ¿qué significa exactamente "correcto"? ¿Qué parte del código se verifica, frente a qué parte es la TCB supuestamente correcta? La desventaja es que pensar demasiado en esto lleva a uno a los agujeros de conejo filosóficos , bueno, "inconveniente" si no disfrutas de esos agujeros de conejo.
La segunda perspectiva es una versión más matemática de la corrección. Cuando se trata de idiomas en matemáticas, a menudo configuramos "modelos" para nuestras "teorías" (o viceversa) y luego intentamos demostrar: (a) todo lo que podemos hacer en la teoría que podemos hacer en el modelo, y (b) todo lo que podemos hacer en el modelo podemos hacerlo en la teoría. (Estos son Solidez y Completitudteoremas Cuál depende de si usted "comenzó" a partir de la teoría sintáctica o del modelo semántico.) Con esta mentalidad podemos pensar en su implementación de verificación de tipo como un modelo particular para la teoría de tipo en cuestión. Por lo tanto, querrá probar esta correspondencia bidireccional entre lo que puede hacer su implementación y lo que la teoría dice que debería poder hacer. La ventaja de esta perspectiva es que realmente se centra en si ha cubierto todos los casos de esquina, si su implementación está completa en el sentido de no omitir ningún programa que debería aceptar como tipo seguro, y si su implementación es sólida la sensación de no dejar entrar ningún programa que debería rechazar como mal escrito. La desventaja es que es probable que su prueba de correspondencia esté bastante separada de la implementación misma,
fuente