Mi piace molto questa domanda. Non ne so molto, ma ho alcune cose (assistito dall'articolo di Wikipedia , che ha alcune tabelle pulite e simili):
Penso che i tipi di somma / tipi di unione ( ad esempio data Either a b = Left a | Right b
) siano equivalenti alla disgiunzione inclusiva . E anche se non conosco molto bene Curry-Howard, penso che questo lo dimostri. Considera la seguente funzione:
andImpliesOr :: (a,b) -> Either a b
andImpliesOr (a,_) = Left a
Se capisco le cose correttamente, il tipo dice che ( a ∧ b ) → ( a ★ b ) e la definizione dice che questo è vero, dove ★ è o inclusivo o esclusivo o, a seconda di quale Either
rappresenta. Hai una Either
rappresentanza esclusiva o, ⊕; tuttavia, ( a ∧ b ) ↛ ( a ⊕ b ). Ad esempio, ⊤ ∧ ⊤ ≡ ⊤, ma ⊤ ⊕ ⊥ ≡ ⊥ e ⊤ ↛ ⊥. In altre parole, se sia a che b sono vere, allora l'ipotesi è vera ma la conclusione è falsa, e quindi questa implicazione deve essere falsa. Tuttavia, chiaramente, ( a ∧ b ) → ( a ∨ b ), poiché se sia a che b sono veri, allora almeno uno è vero. Quindi, se le unioni discriminate sono una qualche forma di disgiunzione, devono essere la varietà inclusiva. Penso che questo sia una prova, ma sentiti più che libero di disilludermi di questa nozione.
Allo stesso modo, le tue definizioni di tautologia e assurdità come funzione di identità e funzioni non terminanti, rispettivamente, sono un po 'sbagliate. La vera formula è rappresentata dal tipo di unità , che è il tipo che ha un solo elemento ( data ⊤ = ⊤
; spesso scritto ()
e / o Unit
in linguaggi di programmazione funzionale). Questo ha senso: poiché è garantito che quella tipologia sia abitata, e poiché c'è un solo possibile abitante, deve essere vero. La funzione identità rappresenta solo la particolare tautologia che a → a .
Il tuo commento sulle funzioni non terminanti è, a seconda di cosa intendevi precisamente, di più. Curry-Howard funziona sul sistema dei tipi, ma la non terminazione non è codificata lì. Secondo Wikipedia , relativa alla non-terminazione è un problema, come l'aggiunta produce logiche incoerenti ( ad esempio , posso definire wrong :: a -> b
da wrong x = wrong x
, e quindi “dimostrare” che un → b per ogni una e b ). Se questo è ciò che intendevi per "assurdità", allora hai esattamente ragione. Se invece intendevi l'affermazione falsa, allora quello che vuoi invece è un qualsiasi tipo disabitato, ad esempio qualcosa definito dadata ⊥
- cioè, un tipo di dati senza alcun modo per costruirlo. Ciò garantisce che non abbia alcun valore e quindi deve essere disabitato, il che equivale a false. Penso che probabilmente potresti anche usare a -> b
, poiché se proibiamo le funzioni non di terminazione, anche questa è disabitata, ma non ne sono sicuro al 100%.
Wikipedia dice che gli assiomi sono codificati in due modi diversi, a seconda di come interpreti Curry-Howard: o nei combinatori o nelle variabili. Penso che la vista combinatore significhi che le funzioni primitive che ci vengono fornite codificano le cose che possiamo dire per impostazione predefinita (simile al modo in cui il modus ponens è un assioma perché l'applicazione della funzione è primitiva). E penso che la vista variabile possa effettivamente significare la stessa cosa: i combinatori, dopo tutto, sono solo variabili globali che sono funzioni particolari. Per quanto riguarda i tipi primitivi: se ci penso correttamente, penso che i tipi primitivi siano le entità, gli oggetti primitivi di cui stiamo cercando di dimostrare le cose.
Secondo il mio corso di logica e semantica, il fatto che ( a ∧ b ) → c ≡ a → ( b → c ) (e anche che b → ( a → c )) è chiamato legge di equivalenza delle esportazioni, almeno in deduzione naturale prove. All'epoca non avevo notato che si trattava solo di curry, vorrei averlo fatto, perché è fantastico!
Mentre ora abbiamo un modo per rappresentare la disgiunzione inclusiva , non abbiamo un modo per rappresentare la varietà esclusiva. Dovremmo essere in grado di utilizzare la definizione di disgiunzione esclusiva per rappresentarla: a ⊕ b ≡ ( a ∨ b ) ∧ ¬ ( a ∧ b ). Non so come scrivere la negazione, ma so che ¬ p ≡ p → ⊥, e sia l'implicazione che la falsità sono facili. Dovremmo quindi poter rappresentare la disgiunzione esclusiva mediante:
data ⊥
data Xor a b = Xor (Either a b) ((a,b) -> ⊥)
Questo definisce ⊥
essere il tipo vuoto senza valori, che corrisponde alla falsità; Xor
viene quindi definito per contenere sia ( e ) Either
un a o un b ( o ) e una funzione ( implicazione ) da (a, b) ( e ) al tipo inferiore ( falso ). Tuttavia, non ho idea di cosa significhi . ( Modifica 1: ora lo faccio, vedi il paragrafo successivo!) Poiché non ci sono valori di tipo (a,b) -> ⊥
(ci sono?), Non riesco a capire cosa significherebbe in un programma. Qualcuno conosce un modo migliore per pensare a questa definizione oa un'altra? ( Modifica 1: Sì, camccann .)
Modifica 1: grazie alla risposta di camccann (in particolare, i commenti che ha lasciato per aiutarmi), penso di vedere cosa sta succedendo qui. Per costruire un valore di tipo Xor a b
, devi fornire due cose. Primo, un testimone dell'esistenza di un elemento di uno a
o b
come primo argomento; cioè a Left a
o a Right b
. E secondo, una prova che non ci sono elementi di entrambi i tipi a
e b
- in altre parole, una prova che (a,b)
è disabitata - come secondo argomento. Dato che sarai in grado di scrivere una funzione solo da (a,b) -> ⊥
if (a,b)
è disabitata, cosa significa che sia così? Ciò significherebbe che una parte di un oggetto di tipo(a,b)
non poteva essere costruito; in altre parole, che almeno uno, e forse entrambi, a
e anche loro b
sono disabitati! In questo caso, se stiamo pensando al pattern matching, non potresti possibilmente pattern-match su una tale tupla: supponendo che b
sia disabitata, cosa scriveremmo che potrebbe corrispondere alla seconda parte di quella tupla? Pertanto, non possiamo combinarlo con modelli, il che potrebbe aiutarti a capire perché questo lo rende disabitato. Ora, l'unico modo per avere una funzione totale che non richiede argomenti (come questa deve essere, poiché (a,b)
è disabitata) è che anche il risultato sia di tipo disabitato - se stiamo pensando a questo da una prospettiva di corrispondenza dei modelli, questo significa che anche se la funzione non ha casi, non esiste un corpo possibile potrebbe avere entrambi, quindi va tutto bene.
Molto di questo sono io che penso ad alta voce / provo (si spera) le cose al volo, ma spero che sia utile. Consiglio vivamente l'articolo di Wikipedia ; Non l'ho letto in alcun dettaglio, ma le sue tabelle sono un riassunto davvero carino ed è molto completo.