Bem, algo conhecido como parametridade nos diz que, se considerarmos o subconjunto puro de ML (ou seja, nenhuma recursão infinita refe todas essas coisas estranhas), não há como definir uma função com esse tipo além da que retorna o valor vazio. Lista.
Tudo isso começou com o artigo de Wadler, “ Teoremas de graça! ”. Este artigo, basicamente, nos diz duas coisas:
- Se considerarmos linguagens de programação que satisfazem certas condições, podemos deduzir alguns teoremas interessantes apenas observando a assinatura de tipo de uma função polimórfica (isso é chamado de Teorema da Parametricidade).
- ML (sem recursão infinita
refe todas essas coisas estranhas) satisfaz essas condições.
Do Parametricity Teorema nós sabemos que se nós temos uma função f : 'a list -> 'b list, em seguida, para todos 'a, 'b, 'c, 'de para todas as funções g : 'a -> 'c, h : 'b -> 'dtemos:
map h ∘ f = f ∘ map g
(Observe, fà esquerda tem o tipo 'a list -> 'b liste fà direita é 'c list -> 'd list.)
Somos livres para escolher o que gquisermos, então vamos 'a = 'ce g = id. Agora desde map id = id(fácil de provar por indução na definição de map), temos:
map h ∘ f = f
Agora vamos 'b = 'd = boole h = not. Vamos supor que, para alguns, zs : bool listisso acontece f zs ≠ [] : bool list. É claro que map not ∘ f = fnão se sustenta, porque
(map not ∘ f) zs ≠ f zs
Se o primeiro elemento da lista à direita for true, à esquerda o primeiro elemento é falsee vice-versa!
Isso significa que nossa suposição está errada e f zs = []. Nós terminamos? Não.
Assumimos que 'bé bool. Mostramos que quando fé chamado com type f : 'a list -> bool listpara any 'a, fsempre deve retornar a lista vazia. Pode ser que quando chamamos f, f : 'a list -> unit listpois retorna algo diferente? Nossa intuição nos diz que isso não faz sentido: simplesmente não podemos escrever em ML pura uma função que sempre retorna a lista vazia quando queremos que ela nos forneça uma lista de booleanos e, caso contrário, pode retornar uma lista não vazia! Mas isso não é uma prova.
O que queremos dizer é que fé uniforme : se ela sempre retorna a lista vazia para bool list, deve retornar a lista vazia para unit liste, em geral, qualquer 'a list. É exatamente sobre isso que trata o segundo ponto da lista de marcadores no início da minha resposta.
O documento diz-nos que no ML fdeve tomar relacionados valores relacionados queridos. Não vou entrar em detalhes sobre relações, basta dizer que as listas estão relacionadas se, e somente se, tiverem comprimentos iguais e seus elementos estiverem relacionados em pares (isto é, [x_1, x_2, ..., x_m]e [y_1, y_2, ..., y_n]estão relacionados se e somente se m = ne x_1estiverem relacionados a y_1e x_2está relacionado y_2e assim por diante). E a parte divertida é, no nosso caso, uma vez que fé polimórfico, podemos definir qualquer relação nos elementos das listas!
Vamos escolher um 'a, 'be olhar f : 'a list -> 'b list. Agora olhe f : 'a list -> bool list; já mostramos que, nesse caso, fsempre retorna a lista vazia. Agora postulamos que todos os elementos de 'aestão relacionados a si mesmos (lembre-se, podemos escolher qualquer relação que desejamos), isso implica que qualquer um zs : 'a listesteja relacionado a si mesmo. Como sabemos, fleva valores relacionados aos relacionados, isso significa que f zs : 'b listestá relacionado f zs : bool list, mas a segunda lista tem comprimento igual a zero e, como a primeira está relacionada a ela, ela também está vazia.
Para completar, mencionarei que há uma seção sobre o impacto da recursão geral (possível não terminação) no artigo original de Wadler, e também há um artigo explorando teoremas livres na presença de seq.