Proposições (P -> Q) -> Q
e P \/ Q
são equivalentes.
Existe uma maneira de testemunhar essa equivalência em Haskell:
from :: Either a b -> ((a -> b) -> b)
from x = case x of
Left a -> \f -> f a
Right b -> \f -> b
to :: ((a -> b) -> b) -> Either a b
to = ???
de tal modo que
from . to = id
e to . from = id
?
((a -> b) -> b)
é isomórficaa
: a única implementação possível ég f = f someHardcodedA
.g = const someHardcodedB
a
oub
. Faz sentido.to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))
funcionaria. (Esta é uma prova clássica válida da implicação.)Respostas:
Isso é verdade na lógica clássica, mas não na lógica construtiva.
Na lógica construtiva, não temos lei do meio excluído , ou seja, não podemos começar nosso pensamento com "P é verdadeiro ou P não é verdadeiro".
Classicamente, raciocinamos como:
x :: P
)), retorneLeft x
.nx :: P -> Void
função. Em seguida,absurd . nx :: P -> Q
(que pode pico qualquer tipo, tomamosQ
) e chamar dadaf :: (P -> Q) -> Q)
comabsurd . nx
para obter o valor do tipoQ
.O problema é que não há função geral de um tipo:
Para alguns tipos de concreto existem, por exemplo,
Bool
é habitado para que possamos escrevermas, novamente, em geral, não podemos.
fonte
Não, é impossível. Considere o caso especial em que
Q = Void
.Either P Q
é entãoEither P Void
, o que é isomórficoP
.Portanto, se tivéssemos um termo de função
nós também poderíamos ter um termo
De acordo com a correspondência de Curry-Howard, isso seria uma tautologia na lógica intuicionista :
Mas o exposto acima é a eliminação da dupla negação, que é bem conhecida por ser impossível provar na lógica intuicionista - daí uma contradição. (O fato de podermos provar isso na lógica clássica não é relevante.)
(Nota final: isso pressupõe que o programa Haskell seja encerrado. É claro que, usando recursão infinita
undefined
e maneiras semelhantes de realmente evitar retornar um resultado, podemos habitar qualquer tipo em Haskell.)fonte
Não, não é possível, mas é um pouco sutil. O problema é que as variáveis de tipo
a
eb
são universalmente quantificadas.a
eb
são universalmente quantificados. O chamador escolhe qual é o tipo, então você não pode simplesmente criar um valor de qualquer tipo. Isso implica que você não pode simplesmente criar um valor do tipoEither a b
enquanto ignora o argumentof
. Mas usarf
também é impossível. Sem saber quais tiposa
e quaisb
são, você não pode criar um valor do tipoa -> b
para o qual passarf
. Apenas não há informações suficientes disponíveis quando os tipos são universalmente quantificados.Quanto ao motivo pelo qual o isomorfismo não funciona em Haskell - você tem certeza de que essas proposições são equivalentes em uma lógica intuicionista construtiva? Haskell não implementa uma lógica dedutiva clássica.
fonte
Como outros já apontaram, isso é impossível porque não temos a lei do meio excluído. Deixe-me passar por isso um pouco mais explicitamente. Suponha que tenhamos
e nós estabelecemos
b ~ Void
. Então nós temosAgora, vamos provar a dupla negação da lei do meio excluído , aplicada a uma proposição específica .
Então agora
lem
claramente não pode existir, porquea
pode codificar a proposição de que qualquer configuração da máquina de Turing que eu escolher será interrompida.Vamos verificar se
lem
é suficiente:fonte
Não tenho idéia de se isso é válido em termos de lógica ou o que isso significa para sua equivalência, mas sim, é possível escrever essa função em Haskell.
Para construir um
Either a b
, precisamos de uma
ou de umb
valor. Não temos como construir uma
valor, mas temos uma função que retorna umab
que poderíamos chamar. Para fazer isso, precisamos fornecer uma função que converta ana
em ab
, mas, como os tipos são desconhecidos, poderíamos, na melhor das hipóteses, criar uma função que retorne uma constanteb
. Para obter esseb
valor, não podemos construí-lo de outra maneira que antes, portanto isso se torna um raciocínio circular - e podemos resolvê-lo simplesmente criando um ponto de correção :fonte