Nota: non sono un esperto di teoria delle categorie. Se vuoi una spiegazione precisa che cosa significa Dualità nella Teoria delle Categorie, dovresti chiedere a un matematico.
Il concetto di dualità nella teoria delle categorie può essere considerato come "opposto", ma è un tipo speciale di opposto, uno che conserva la struttura. Ad esempio, il doppio di un grafico diretto è il grafico che ha tutte le frecce invertite. Quindi, il grafico è in un certo senso lo stesso (ha gli stessi bordi e vertici), ma in un certo senso è il contrario.
Un altro esempio è la legge di De Morgan: ∧
e ∨
sono duali, quindi se "doppiamo" ¬(A ∨ B)
, finiamo con ¬A
che è il doppio di A
, ¬B
il doppio di B
, e ∨
il doppio di ∧
, quindi il risultato finale è ¬A ∧ ¬B
... e non abbiamo dovuto memorizzare nulla, era solo una semplice sostituzione meccanica senza pensieri.
Ora, per i tipi di funzione, l'idea è simile a quella per i grafici: il doppio tipo è solo il tipo con tutte le frecce invertite. Quindi, il doppio di (Try[T] ⇒ Unit) ⇒ Unit
è (Try[T] ⇐ Unit) ⇐ Unit
, oppure, se scriviamo le frecce "nel modo giusto" Unit ⇒ (Unit ⇒ Try[T])
, che a causa della associatività destra di ⇒
è solo Unit ⇒ Unit ⇒ Try[T]
.
La ragione per cui la Duality è interessante, è che a causa del fatto che alcune strutture sono preservate e alcune cose sono opposte, sappiamo molto sul Dual semplicemente guardando le proprietà dell'Originale. Torniamo all'esempio del grafico: sappiamo che il doppio grafico ha lo stesso numero di bordi e il numero di vertici, infatti, ha lo stesso insieme di bordi e il set di vertici "specchiato". Ha lo stesso grafico indiretto equivalente. Ha lo stesso numero di cicli. E così via. Ciò significa che alcune proprietà dell'originale vengono trasferite al doppio e alcune proprietà vengono invertite. Quindi, se abbiamo provato o calcolato alcune proprietà dell'originale, otteniamo la prova corrispondente per il doppio gratuitamente.
Inoltre, poiché una sorta di struttura è generalmente preservata tra le due, le librerie che si basano solo sulla struttura funzionano semplicemente con il nuovo tipo senza dover fare nulla.
Gli esempi più noti e ampiamente utilizzati di questo è probabilmente il IObserver
/ IObservable
coppia di interfacce in .NET, che è stata derivata meccanicamente doppiando IEnumerable
/ IEnumerator
, dopo Erik Meijer ha scoperto che la programmazione reattiva / basata sugli eventi è il doppio della programmazione interattiva e quindi il Pattern di progettazione soggetto / osservatore dovrebbe essere il doppio del modello di design di Iterator. La cosa più interessante che viene preservata da questa duplicazione è il fatto che IEnumerable
/ IEnumerator
è una monade (un'istanza della Monade Elenco), e quindi IObserver
/ IObservable
è anche una monade (un'istanza della Continuazione Monad). Sia C♯ che Visual Basic.NET hanno il supporto linguistico integrato per le monade (LINQ Query Comprehensions) e funzionano solo con IObserver
/ IObservable
.
La cosa importante più , tuttavia, è che grazie alla programmazione reattiva di conservazione della struttura, gli eventi possono essere scritti più o meno allo stesso modo della programmazione interattiva con gli iteratori.