Title: Linguaggi di Programmazione Secondo Semestre / 05 - Type / 05.3 - Compatibilità Coercizione e Polimorfismo

Q: Equivalenza dei tipi
A: ## Nominal type equivalence
Def: due tipi sono equivalenti per nome se e solo se hanno lo stesso nome
(lo stesso tipo ridichiarato con lo stesso nome è diverso)
ogni volta che viene definito un nuovo tipo viene introdotto un nuovo nome da quelli esistenti, può essere fatto staticamente
## Duck Typing
guarda semplicemente se le operazioni che faccio nel programma sono supportate dal tipo dato(tipicamente fatto a runtime)
## Structural Type equivalence
l'equivalente viene verificata guardando i fildes della struttura, può essere verificato in maniera statica, bisogna però verificare il check delle operazioni che sono permesse sui tipi (facciamo il duck typing su tutti i sottotipi)
In pochi linguaggi si usano i structural type, tranne nei metalinguaggi che servono per cumunicare tra più linguaggi.
Nei tipi ricorsivi, è molto più facile verificare un equivalenza nominale rispetto ad una strutturale.

Q: Compatibilità dei tipi
A: Def: compatibilità, il tipo T è compatibile con il tipo S se un valore di tipo T è mmessol in un qualsiasi contesto in cui sarebbe richiesto un valore di tipo S.
type coercion e conversion: la type coversion è un meccanismo che crea un ponte tra due tipi, un type coercion è quando la type conversion viene fatta implicitamente e canonicamente nel linguaggio. Per farlo implicitamente invece si può fare il type casting

Q: Def: monomorfi Types/Polimorfi
A: In monomorfi type system, il sistema non accetta generici.
I tipi polimorfi, permettono allo sviluppatore di definire alcune operazioni possibili su tipi astratti passati.

Q: Ad-hoc polimorfismo (overloading)
A: L'overloading significa definire la funzione più volte con tipi di verso come parametri. La scelta di quale funzione utilizzare può essere fatta in maniera statica, e dinamica guardando le lookup tables (quindi bisogna avere delle informazioni sui tipi).
Viene vista come somma di fuzioni di due tipi diversi, con due domini diveri.
$f = g+ h: dom(g) = D, dom(h) = D', D \cap D' = \emptyset$
si può fare anche l'insieme di due funzioni di codominio diverso, reificando i tipi, quindi aggiungere il tipo di ritorno nella definizione della funzione.
esempio: f : D -> O, f: D -> O' diventa f: D x tipo -> OxO'

Q: Polimorfismo universale parametrico
A: Def:Un valore esibisce polimorfismo universale parametrico ( o polimorfismo parametrico, in breve) quando ha un'infinità di tipi diversi, che si ottengono per istanzazione da un unico schema di tipo generale.
polimorfismo parametrico non presuppone alcuna conoscenza dei parametri del tipo, alcuni linguaggi forniscono un operatore di introspezione (instanceof).
Il polimorfismo parametrico cattura l'universalità delle espressioni di tipo, ma a volte è utile esprimere dei vincoli sul quantificatore universale, ad esempio per limitare la quantificazione solo ai tipi con determinate  proprietà.
Si combinano di solito il polimorfismo con il sottotipo, in quanto il polimorfismo è troppo genercico. (∀ T, T <: Comparable, max: T -> T -> T)
In generale qunado si usa il polimorfismo parametrico non si possono fare ipotesi sulla forma dei parametri del tipo. (per questo viene chiamato universale)
Theroems for free:
(essendo che r non sa niente sul tipo di l non può modificarla in base al tipo di dato qindi può solo riordinarla non basandosi sul valore, quindi l'unca informazione è la posizione)
nei linguaggi di programmazzione supportano:
- Polimorfismo esplicito: Quando sono presenti delle annotazioni esplicite, indicando quali tipi devono essere considerati parametri
- Polimorfismo implicito: (di solito nel paradigma funzionale) il programma non può riportare alcuna indicazione di tipo, è invece il controllre dei tipi, a cercare di ottenere per ogni oggetto del linguaggio il suo tipo più generale, dal quale tutti gli altri tipi si possono ottenere per istanziare dei parametri di tipo

Q: Polimorfismo di sottotipo
A: Il polimorfismo è un relazione binaria <: sui tipi in cui S <: T cioè S è sottotipo di T di solito allora, S è un tipo più specifico di T e quindi possiamo utilizzare S in qualsasi posto dove possiamo utilizzare T.
La relazione è un preordine (molte volte preordine parziale).
Tipicamente è utilizzato nei linguaggi object-oriented, ed è di solito implementato ereditarietà.
Il polimorfismo di sottotipo dei record, non ha problemi nella lettura, ma al contrario dobbiamo utilizzarla in maniera controvariante (cioè l'opposto) per le scritture.
Le funzioni di consumo di soito sono controvarianti, mentre quelli di produzione sono covarianti
## Estensionale, Intensionale
Polimorfismo estensionale:
## Esempi
Alcuni Esempi:
type A2B: Animal -> Bool
type D2B: Dog -> Bool
allora A2B <: D2B
type U2A: Unit -> Animal
type U2D: Unit -> Dog
allora U2D <: U2A
type D2D: Dog -> Dog
type A2E: Animal -> EliteDog
allora A2E <: D2D

Q: Tipi maybe
A: Option di rust

Q: Polimorfismo parametrico Universale Ibrido
A: ## Polimorfismo Parametroco Universale Ibrido
I tipi parametrici sono i tipi che supportano un tipo come parametro (es vector).
## Polimorfismo Ibrido
Alcuni linguaggi forniscono un operatore di introspezione (instanceof) che consente all'utente di verificare se un valore appartiene a un tipo.
Si può avere anche il sottotipaggio in profondità su queste strutture benchè non ci siano accessi in scrittura/inserimento, o al contrario un sottotipaggio controvarianza.
## Array
## Implementazione C++
C++ implementa staticamente cioè il compilatore crea una copia di codice per ogni istanza utilizzata
## Implementazione Java
Java usa la type erasure, durante la compilazione cancella tutti i parametri e tutti gli oggetti diventano di tipo Top (Object, se non specificato).
Questo produce problemi come nell'utilizzo della instanceof e la new che non sono più applicabili

Q: Prototipi
A: I prototipi delegano parti della loro implemntazione da altri oggetti (js è famoso per i prototipi)
Per creare un oggetto o si usa la forma ex-nihlo (dal nulla) cone la notazione a  tra {} (non assegna nessun proptotipo)
clonazione con la new crea un oggetto facendo la copia di uno esistente
I prototipi sono oggetti (quindi già un istanza che viene copiata), inoltre i prototipi possono cambiare i delegati durante l'esecuzione.

Q: Encapsulation, Abstraction, Inheritance, Dinamic Dispatch
A: ## Encapsulation
L'incapsulamento e l'information i linguaggi a OO permettono di definire un oggetto nascondedo parti di esso.
Infatti si distinguono la parte pubblica e la parte privata dell'oggetto. La parte pubblica è solitamente detta Interfaccia
## Abstraction
Interfacce sono un ponte linguistico tra classi e tipi. Queste astrazioni permettono il principio di astrazione. le interfacce specificano dei metodi che le classi devono implementare
Non esiste solo interfaccia classe ma anche interfaccia e interfaccia.
## Inheritance
(Mentre nei sistema di tipi strotturali la relazione di sottotipaggio è basta tra la corrispondenza tra gli elementi di S rispetto a quelli di T, nei linguaggi basti sulle classi è quella di adottare uno stile nominale (estensivo)).
L'ereditarietà è il sottotipaggio tra classi. oltre ad ereditare l'interfaccia dall'interface copia anche lo stato.
Quando si applica l'erederitarietà si può avere lo shadowing delle variabili, cioè ridefinre le variabili già dichiarate
Inoltre c'è l'override dei metodi cioè rimpiazzare la vecchia implementazione con una nuova definita nella classe più specifica.
Una differenza tra l'overriding dei metodi e lo shadowing delle variabili è che il primo è risolto dinamicamente, mentre il secondo è risolto staticamente.
Nell'overriding di un metodo, è la classe effettiva dell'oggetto (da quale classe è stato istanziato) a determinare a quale metodo verrà inviata l'invocazione Al contrario, lo shadowing delle variabili viene risolto staticamente, cioè indicando esplicitamente a quale variabile si vuole
accedere
Visibilità: private public, protected (che serve per essere visibile all'interno del package)
## Dynamic Dispatch
Nel early binding (dell’overloading) si utilizzano informazioni statiche (sul tipo delle variabili) per risolvere l'ambiguità e legare il nome. Al contrario, nel late binding le informazioni sono disponibili solo a tempo di esecuzione (i tipi degli oggetti reali)

Q: Costrutturi
A: Creano l'oggetto allocando la memoria e di solito assegnando qualche stato
Sia sulla heap che sulla stack (non in java dove popolano tutti la heap)

Q: Ereditarietà singola e multipla
A: In java essite solo l'ereditarietà singola per quindi è un albero.
In altri come il C++ supportano l'ereditareità multipla, (quindi un DAG) che può dare problemi concettuali come il confilitto dei nomi.

Q: Metodi statici
A: I metodi statici sono risolti staticamente dal compilatore e non si può utilizzare l'overriding ma solamente l'overloading come le funzioni normali
Esempio molto esplicativo