Para entender essa afirmação, primeiro precisamos entender o que um sistema de tipo estático nos compra. Em essência, o que um sistema de tipo estático nos oferece é uma garantia: se o tipo de programa verificar, uma certa classe de comportamentos em tempo de execução não poderá ocorrer.
Isso soa ameaçador. Bem, um verificador de tipos é semelhante a um verificador de teoremas. (Na verdade, pelo isomorfismo de Curry-Howard, eles são a mesma coisa.) Uma coisa que é muito peculiar nos teoremas é que, quando você prova um teorema, prova exatamente o que o teorema diz, nada mais. (É por exemplo, por que, quando alguém diz "Eu provei este programa correto", você deve sempre perguntar "por favor defina 'correto'".) O mesmo se aplica aos sistemas de tipos. Quando dizemos "um programa é seguro para o tipo", o que queremos dizer não é que nenhum erro possível possa ocorrer. Só podemos dizer que os erros que o sistema de tipos promete impedir não podem ocorrer.
Portanto, os programas podem ter infinitos comportamentos de tempo de execução diferentes. Desses, infinitamente muitos são úteis, mas também infinitos são "incorretos" (para várias definições de "correção"). Um sistema de tipo estático nos permite provar que um determinado conjunto finito e fixo desses infinitos comportamentos incorretos de tempo de execução não pode ocorrer.
A diferença entre sistemas de tipos diferentes é basicamente em qual, quantos e quão complexos comportamentos de tempo de execução eles podem provar não ocorrer. Sistemas de tipo fraco, como o de Java, só podem provar coisas muito básicas. Por exemplo, Java pode provar que um método digitado como retornando a String
não pode retornar a List
. Mas, por exemplo, pode não provar que o método não não vai voltar. Também não pode provar que o método não gera uma exceção. E não pode provar que não retornará o erro errado String
- qualquer String
um satisfará o verificador de tipos. (E, claro, mesmo null
vai satisfazê-lo também.) Há ainda coisas muito simples que Java não pode provar, que é por isso que temos exceções, como ArrayStoreException
, ClassCastException
ou todo mundo favorito, o NullPointerException
.
Sistemas de tipos mais poderosos como o da Agda também podem provar coisas como "retornará a soma dos dois argumentos" ou "retorna a versão classificada da lista passada como argumento".
Agora, o que os designers de Elm querem dizer com a afirmação de que eles não têm exceções de tempo de execução é que o sistema de tipos de Elm pode provar a ausência de (uma porção significativa de) comportamentos de tempo de execução que em outros idiomas não podem ser comprovados como não ocorrendo e, portanto, podem levar comportamento errado no tempo de execução (que, na melhor das hipóteses, significa uma exceção, na pior das hipóteses significa uma falha e, na pior das hipóteses, significa nenhuma falha, nenhuma exceção e apenas um resultado silenciosamente errado).
Portanto, eles não estão dizendo "não implementamos exceções". Eles estão dizendo "coisas que seriam exceções de tempo de execução em linguagens típicas com as quais os programadores comuns que vêm para Elm teriam experiência são capturados pelo sistema de tipos". Obviamente, alguém vindo de Idris, Agda, Guru, Epigram, Isabelle / HOL, Coq ou idiomas semelhantes verá Elm como muito fraco em comparação. A declaração é mais voltada para programadores Java, C♯, C ++, Objective-C, PHP, ECMAScript, Python, Ruby, Perl, ... típicos.