J'aime vraiment cette question. Je ne sais pas grand-chose, mais j'ai quelques petites choses (assisté par l'article de Wikipédia , qui contient des tableaux soignés et autres):
Je pense que les types de somme / types d'union ( par exemple data Either a b = Left a | Right b
) sont équivalents à la disjonction inclusive . Et, bien que je ne connaisse pas très bien Curry-Howard, je pense que cela le démontre. Considérez la fonction suivante:
andImpliesOr :: (a,b) -> Either a b
andImpliesOr (a,_) = Left a
Si je comprends bien les choses, le type dit que ( a ∧ b ) → ( a ★ b ) et la définition dit que c'est vrai, où ★ est soit inclusif, soit exclusif ou, selon ce que Either
représente. Vous avez Either
représentant exclusif ou, ⊕; cependant, ( a ∧ b ) ↛ ( a ⊕ b ). Par exemple, ⊤ ∧ ⊤ ≡ ⊤, mais ⊤ ⊕ ⊥ ≡ ⊥ et ⊤ ↛ ⊥. En d'autres termes, si a et b sont tous les deux vrais, alors l'hypothèse est vraie mais la conclusion est fausse, et donc cette implication doit être fausse. Cependant, clairement, ( a ∧ b ) → ( a ∨ b ), puisque si a et b sont tous les deux vrais, alors au moins un est vrai. Ainsi, si les unions discriminées sont une forme de disjonction, elles doivent être la variété inclusive. Je pense que c'est une preuve, mais je me sens plus que libre de me désabuser de cette notion.
De même, vos définitions de la tautologie et de l'absurdité en tant que fonction d'identité et fonctions non terminales, respectivement, sont un peu décalées. La vraie formule est représentée par le type d'unité , qui est le type qui n'a qu'un seul élément ( data ⊤ = ⊤
; souvent orthographié ()
et / ou Unit
dans les langages de programmation fonctionnels). Cela a du sens: puisque ce type est garanti d'être habité, et comme il n'y a qu'un seul habitant possible, cela doit être vrai. La fonction d'identité représente simplement la tautologie particulière que a → a .
Votre commentaire sur les fonctions sans terminaison est, en fonction de ce que vous vouliez précisément dire, plus offensif. Curry-Howard fonctionne sur le système de types, mais la non-terminaison n'y est pas codée. Selon Wikipedia , traiter la non-terminaison est un problème, car l'ajouter produit des logiques incohérentes ( par exemple , je peux définir wrong :: a -> b
par wrong x = wrong x
, et donc «prouver» que a → b pour tout a et b ). Si c'est ce que vous entendez par «absurdité», alors vous avez tout à fait raison. Si à la place vous vouliez dire la fausse déclaration, alors ce que vous voulez à la place est n'importe quel type inhabité, par exemple quelque chose défini pardata ⊥
- c'est-à-dire un type de données sans aucun moyen de le construire. Cela garantit qu'il n'a aucune valeur du tout et qu'il doit donc être inhabité, ce qui équivaut à false. Je pense que vous pourriez probablement également l'utiliser a -> b
, car si nous interdisons les fonctions sans terminaison, cela est également inhabité, mais je ne suis pas sûr à 100%.
Wikipedia dit que les axiomes sont codés de deux manières différentes, selon la façon dont vous interprétez Curry-Howard: soit dans les combinateurs, soit dans les variables. Je pense que la vue combinateur signifie que les fonctions primitives qui nous sont données codent les choses que nous pouvons dire par défaut (de la même manière que modus ponens est un axiome parce que l'application de la fonction est primitive). Et je pense que la vue variable peut en fait signifier la même chose - les combinateurs, après tout, ne sont que des variables globales qui sont des fonctions particulières. Quant aux types primitifs: si j'y pense correctement, alors je pense que les types primitifs sont les entités - les objets primitifs sur lesquels nous essayons de prouver les choses.
D'après ma classe de logique et de sémantique, le fait que ( a ∧ b ) → c ≡ a → ( b → c ) (et aussi que b → ( a → c )) est appelé loi d'équivalence d'exportation, du moins en déduction naturelle preuves. Je n'ai pas remarqué à l'époque que c'était juste du curry - j'aurais aimé l'avoir, parce que c'est cool!
Bien que nous ayons maintenant un moyen de représenter la disjonction inclusive , nous n'avons pas de moyen de représenter la variété exclusive. On devrait pouvoir utiliser la définition de la disjonction exclusive pour la représenter: a ⊕ b ≡ ( a ∨ b ) ∧ ¬ ( a ∧ b ). Je ne sais pas comment écrire la négation, mais je sais que ¬ p ≡ p → ⊥, et l'implication et le mensonge sont faciles. On devrait ainsi pouvoir représenter la disjonction exclusive par:
data ⊥
data Xor a b = Xor (Either a b) ((a,b) -> ⊥)
Cela définit ⊥
être le type vide sans valeurs, ce qui correspond à la fausseté; Xor
est alors défini pour contenir à la fois ( et ) Either
un a ou un b ( ou ) et une fonction ( implication ) de (a, b) ( et ) au type inférieur ( faux ). Cependant, je n'ai aucune idée de ce que cela signifie . ( Edit 1: Maintenant je le fais, voir le paragraphe suivant!) ( Edit 1: Oui, camccann .) Puisqu'il n'y a pas de valeurs de type (a,b) -> ⊥
(y a-t-il?), Je ne peux pas comprendre ce que cela signifierait dans un programme. Quelqu'un connaît-il une meilleure façon de penser à cette définition ou à une autre?
Edit 1: Grâce à la réponse de camccann (plus particulièrement, les commentaires qu'il a laissés dessus pour m'aider), je pense voir ce qui se passe ici. Pour construire une valeur de type Xor a b
, vous devez fournir deux choses. Premièrement, un témoin de l'existence d'un élément de l'un a
ou b
de l' autre ou comme premier argument; c'est-à-dire a Left a
ou a Right b
. Et deuxièmement, une preuve qu'il n'y a pas d'éléments des deux types a
et b
- en d'autres termes, une preuve (a,b)
inhabitée - comme deuxième argument. Puisque vous ne pourrez écrire une fonction qu'à partir de (a,b) -> ⊥
if (a,b)
est inhabité, qu'est-ce que cela signifie pour que ce soit le cas? Cela signifierait qu'une partie d'un objet de type(a,b)
ne peut pas être construit; en d'autres termes, qu'au moins un, et peut-être les deux,a
et b
sont inhabitée aussi bien! Dans ce cas, si nous pensons à la correspondance de motifs, vous ne pourriez pas éventuellement correspondre à des motifs sur un tel tuple: en supposant que ce b
soit inhabité, qu'écririons-nous qui pourrait correspondre à la deuxième partie de ce tuple? Ainsi, nous ne pouvons pas faire de correspondance de motif avec lui, ce qui peut vous aider à comprendre pourquoi cela le rend inhabité. Maintenant, le seul moyen d'avoir une fonction totale qui ne prend aucun argument (comme celui-ci doit, car il (a,b)
est inhabité) est que le résultat soit également d'un type inhabité - si nous y réfléchissons du point de vue de la correspondance de motifs, cela signifie que même si la fonction n'a pas de cas, il n'y a pas de corps possible il pourrait avoir l'un ou l'autre, et donc tout va bien.
Une grande partie de cela me fait penser à haute voix / prouver (espérons-le) des choses à la volée, mais j'espère que c'est utile. Je recommande vraiment l'article Wikipédia ; Je ne l'ai pas lu en détail, mais ses tableaux sont un très bon résumé et il est très complet.