Para entender esta afirmación, primero tenemos que entender qué nos compra un sistema de tipo estático. En esencia, lo que nos da un sistema de tipo estático es una garantía: si el tipo de programa verifica, no puede ocurrir una determinada clase de comportamientos de tiempo de ejecución.
Eso suena siniestro. Bueno, un verificador de tipo es similar a un verificador de teoremas. (En realidad, según el isomorfismo de Curry-Howard, son lo mismo.) Una cosa que es muy peculiar acerca de los teoremas es que cuando se prueba un teorema, se demuestra exactamente lo que dice el teorema, nada más. (Por ejemplo, cuando alguien dice "He demostrado que este programa es correcto", siempre debe preguntar "defina 'correcto'"). Lo mismo es cierto para los sistemas de tipos. Cuando decimos "es un programa de tipo seguro", lo que queremos decir es que no que no se produzca ninguna posibilidad de error. Solo podemos decir que los errores que el sistema de tipos nos promete evitar no pueden ocurrir.
Por lo tanto, los programas pueden tener infinitos comportamientos de tiempo de ejecución diferentes. De ellos, infinitamente muchos son útiles, pero también infinitamente muchos son "incorrectos" (para varias definiciones de "corrección"). Un sistema de tipo estático nos permite demostrar que un cierto conjunto finito y fijo de esos infinitos comportamientos incorrectos de tiempo de ejecución no puede ocurrir.
La diferencia entre los diferentes sistemas de tipos radica básicamente en cuál, cuántos y cuán complejos pueden ser los comportamientos de tiempo de ejecución que no se producen. Los sistemas de tipo débil como el de Java solo pueden probar cosas muy básicas. Por ejemplo, Java puede demostrar que un método que se escribe como devolver a String
no puede devolver a List
. Pero, por ejemplo, puede no demostrar que el método no no volverá. Tampoco puede probar que el método no arroje una excepción. Y no puede probar que no devolverá el error String
; cualquiera String
satisfará el verificador de tipo. (Y, por supuesto, incluso null
satisfaga él también.) Incluso hay cosas muy simples que Java no se puede demostrar, por lo que tenemos excepciones como ArrayStoreException
, ClassCastException
o favorito de todos, el NullPointerException
.
Los sistemas de tipos más potentes como el de Agda también pueden probar cosas como "devolverá la suma de los dos argumentos" o "devuelve la versión ordenada de la lista pasada como argumento".
Ahora, lo que los diseñadores de Elm quieren decir con la afirmación de que no tienen excepciones de tiempo de ejecución es que el sistema de tipos de Elm puede demostrar la ausencia de (una porción significativa de) comportamientos de tiempo de ejecución que en otros idiomas no se puede demostrar que no ocurran y, por lo tanto, podrían conducir a a un comportamiento erróneo en tiempo de ejecución (que en el mejor de los casos significa una excepción, en el peor de los casos significa un bloqueo, y en el peor de los casos significa sin bloqueo, sin excepción y simplemente un resultado silenciosamente incorrecto).
Por lo tanto, están no diciendo "no implementamos excepciones". Están diciendo "cosas que serían excepciones de tiempo de ejecución en lenguajes típicos con los que los programadores típicos que llegarían a Elm tendrían experiencia, son atrapados por el sistema de tipos". Por supuesto, alguien que viene de Idris, Agda, Guru, Epigram, Isabelle / HOL, Coq o idiomas similares verá a Elm como bastante débil en comparación. La declaración está más dirigida a los programadores típicos de Java, C♯, C ++, Objective-C, PHP, ECMAScript, Python, Ruby, Perl, ...