Le informazioni sul tipo di runtime si trovano comunemente nelle implementazioni di linguaggi OOP, che contengono un "tag di tipo" con ogni oggetto. Avere tali informazioni consente, ad esempio, di scrivere codice come
void foo(Object o) {
if (o instanceof SomeClass) {
...
}
}
che è una forma di controllo del tipo di runtime. Il "tag type" viene spesso fornito gratuitamente, poiché ogni oggetto ha bisogno di un puntatore alla Virtual Method Table e solo questo identifica il tipo di runtime dell'oggetto.
In Haskell, tuttavia, non è necessario un tag di questo tipo o per i puntatori ai VMT. Il linguaggio è stato progettato senza alcun tipo di operatore instanceof
in modo che le implementazioni non debbano fornire alcun tipo di tag in fase di esecuzione. Ciò porta anche ad una teoria sottostante più interessante, dal momento che otteniamo garanzie di parametricità sul codice, note anche come "teoremi gratis!". Per esempio la seguente funzione
f :: [a] -> [a]
f = .... -- whatever
può non essere implementato in modo che f [1,2] = [2,3]
. Ciò è dovuto al fatto che non esiste, in modo dimostrabile, alcun modo di produrre 3
per f
. L'intuizione è che f
deve produrre un a
e non può controllare che a=Int
in fase di esecuzione (nessun tag di tipo), quindi l'output di f
può includere solo elementi trovati nel suo input. Questa garanzia viene solo dalla digitazione sopra riportata, senza nemmeno preoccuparsi di come lo strumento f
sia effettivamente implementato.
Se si vuole veramente un instanceof
equivalente, è possibile utilizzare Typeable
per questo:
f :: Typeable a => [a] -> [a]
f [] = []
f (x:xs) = case cast x of
Just (y :: Int) -> [2,3]
Nothing -> x:x:xs
Ciò restituirà [2,3]
su tutte le liste non vuote se interi. In fase di esecuzione, verrà passato un tag di tipo che consente di verificare a=Int
.
Che cosa significa "tempo di esecuzione" per te? Puoi dare un esempio di qualcosa che sarebbe di tipo "runtime" e qualcosa che non sarebbe di tipo "runtime"? Intendi "Haskell ha informazioni sul tipo di esecuzione?" –
Tipo run-time = il tipo (in senso teorico del tipo) di una variabile nel momento in cui il programma viene eseguito su un processore fisico raggiungibile/identificabile dal compilatore di lingua al momento della compilazione della lingua. Esempio: C++ con RTTI on e off. Immagino si possa capire come il compilatore usi le informazioni sul tipo di runtime al momento della compilazione per decidere se qualcosa compila o meno. – markolaban
Non sono presenti informazioni sui tipi di dati in fase di esecuzione. I dati che rappresentano un intero o un albero o lista non sono "etichettati" con ulteriori metadati che indicano il tipo. Tutto il controllo del tipo viene eseguito al momento della compilazione. Per questo motivo, wrapping/unwrapping non sicuriCoerce e newtype non hanno costi di runtime. Questo naturalmente viene fornito con l'avvertenza che è possibile (esplicitamente) scegliere di memorizzare una rappresentazione del tipo di dati in fase di esecuzione. – user2407038