Qualcuno può spiegare la digitazione dipendente da me? Ho poca esperienza in Haskell, Cayenne, Epigram o in altri linguaggi funzionali, quindi il più semplice dei termini che puoi usare, più lo apprezzerò!Che cos'è la digitazione dipendente?
risposta
Considerare questo: in tutti i linguaggi di programmazione decenti è possibile scrivere funzioni, ad es.
def f(arg) = result
Qui, f
assume un valore arg
e calcola un valore result
. È una funzione da valori a valori.
Ora, alcune lingue consentono di definire i valori polimorfiche (aka generici):
def empty<T> = new List<T>()
Qui, empty
prende un tipo T
e calcola un valore. È una funzione da tipi a valori.
Di solito, si può anche avere definizioni generiche tipo:
type Matrix<T> = List<List<T>>
Questa definizione prende un tipo e restituisce un tipo. Può essere visto come una funzione da tipi a tipi.
Questo per quanto riguarda le lingue ordinarie. Una lingua è chiamata tipicamente digitata se offre anche la quarta possibilità, ovvero la definizione di funzioni da valori a tipi. O in altre parole, la parametrizzazione di una definizione di tipo per un valore di:
type BoundedInt(n) = {i:Int | i<=n}
Alcuni linguaggi tradizionali hanno una qualche forma falsi di questo che non deve essere confuso. Per esempio. in C++, i modelli possono assumere valori come parametri, ma devono essere costanti in fase di compilazione quando applicati. Non così in un linguaggio tipicamente dipendente. Per esempio, ho potuto utilizzare il tipo di cui sopra in questo modo:
def min(i : Int, j : Int) : BoundedInt(j) =
if i < j then i else j
Edit: Ecco, della funzione tipo di risultato dipende sul valore dell'argomento reale j
, in tal modo la terminologia.
Tuttavia, l'esempio 'BoundedInt' non è in realtà un tipo di perfezionamento? Questo è "abbastanza vicino" ma non esattamente il tipo di "tipi dipendenti" che, ad esempio, Idris menziona per prima cosa in un tutorial su dep.typing. – Noein
@Noein, i tipi di raffinatezza sono in effetti una semplice forma di tipi dipendenti. –
citando il libro Tipi e linguaggi di programmazione (30,5):
Gran parte di questo libro è stata interessata con formalizzare l'astrazione meccanismi di vario genere. Nel lambda-calcolo semplicemente digitato, abbiamo formalizzato l'operazione di prendere un termine e astraendo un sottotermine , ottenendo una funzione che può successivamente essere istanziata da applicandolo a termini differenti. Nel sistema
F
, abbiamo considerato l'operazione di prendere un termine e di estrarre un tipo, ottenendo un termine che può essere istanziato applicandolo a vari tipi. Nel numeroλω
, abbiamo ricapitolato i meccanismi del lambda-calcolo semplicemente "uno di livello superiore", prendendo un tipo e estraendo una sottoespressione per ottenere un operatore di tipo che può essere istanziato in seguito applicandolo a tipi diversi. Un modo conveniente di pensare a tutte queste forme di astrazione è in termini di famiglie di espressioni, indicizzate da altre espressioni . Un'ordinaria astrazione lambdaλx:T1.t2
è una famiglia di termini[x -> s]t1
indicizzati dai terminis
. Allo stesso modo, un'astrazione di tipoλX::K1.t2
è una famiglia di termini indicizzati dai tipi e un operatore di tipo è una famiglia di tipi indicizzati per tipo.
λx:T1.t2
famiglia di termini indicizzati dai termini
λX::K1.t2
famiglia di termini indicizzati dai tipi
λX::K1.T2
famiglia di tipi indicizzate da tipiGuardando questa lista, è chiaro che c'è una possibilità che abbiamo Non ancora considerati: famiglie di tipi indicizzati in termini. Questa forma di astrazione è stata anche ampiamente studiata, sotto la rubrica dei tipi dipendenti.
Se vi capita di conoscere C++ è facile fornire un esempio motivante:
Diciamo che abbiamo un certo tipo di contenitore e due istanze dello stesso
typedef std::map<int,int> IIMap;
IIMap foo;
IIMap bar;
e considerare questo frammento di codice (si può assumere foo non è vuoto):
IIMap::iterator i = foo.begin();
bar.erase(i);
Questo è evidente garbage (e probabilmente corrompe la struttura dei dati s), ma sarà tipicamente corretto, dal momento che "iteratore in foo" e "iteratore in barra" sono dello stesso tipo, IIMap::iterator
, anche se sono completamente incompatibili semanticamente.
Il problema è che un tipo iteratore non dovrebbe dipendere solo sul contenitore tipo ma in realtà sul contenitore oggetto, cioè dovrebbe essere un "Tipo di utente non statico":
foo.iterator i = foo.begin();
bar.erase(i); // ERROR: bar.iterator argument expected
Tale caratteristica, la capacità di esprimere un tipo (foo.iterator) che dipende da un termine (foo), è esattamente ciò che dipende dalla digitazione.
Il motivo per cui non si vede spesso questa funzionalità è perché apre una grande quantità di worm: si finisce improvvisamente in situazioni in cui, per verificare in fase di compilazione se due tipi sono uguali, si finisce per avere per dimostrare che due espressioni sono equivalenti (fornirà sempre lo stesso valore in fase di esecuzione). Di conseguenza, se si confronta wikipedia list of dependently typed languages con il suo list of theorem provers si potrebbe notare una somiglianza sospetta. ;-)
tipi dipendenti consentono grande insieme di logic errors essere eliminati in fase di compilazione . Per illustrare questo in considerazione le seguenti specifiche sulla funzione f
:
Funzione
f
deve prendere solo anche interi come input.
Senza di tipi dipendenti si potrebbe fare qualcosa di simile:
def f(n: Integer) := {
if n mod 2 != 0 then
throw RuntimeException
else
// do something with n
}
Qui il compilatore non può rilevare se n
è davvero ancora, cioè, dal punto di vista del compilatore la seguente espressione è ok:
f(1) // compiles OK despite being a logic error!
Questo programma viene eseguito e genera un'eccezione in fase di esecuzione, ovvero il programma ha un errore logico.
Ora, tipi dipendenti consentono di essere molto più espressivo e si dovrebbe consentire di scrivere qualcosa del genere:
def f(n: {n: Integer | n mod 2 == 0}) := {
// do something with n
}
Qui n
è di tipo dipendente {n: Integer | n mod 2 == 0}
. Potrebbe essere utile per leggere ad alta voce come
n
è un membro di un insieme di numeri tali che ogni intero è divisibile per 2.
In questo caso il compilatore di rilevare in fase di compilazione un errore logico in cui è stato superato un numero dispari di f
e da impedire la programma da eseguire, in primo luogo:
f(1) // compiler error
- 1. Limiti della digitazione dipendente in Idris
- 2. Digitazione dinamica senza digitazione anatra?
- 3. Mostra testo durante la digitazione
- 4. Come funziona la digitazione ibrida?
- 5. stampa lentamente (Simula la digitazione)
- 6. Codifica che minimizza la lettura errata/l'errata digitazione/l'errata registrazione?
- 7. Dalla digitazione statica alla digitazione dinamica
- 8. Xcode scorre il testo durante la digitazione
- 9. Aggiornamento casella di testo durante la digitazione
- 10. Come si simula la digitazione con jQuery?
- 11. Kendo UI Datepicker disabilita la digitazione
- 12. Combobox wrap text durante la digitazione
- 13. Perché DateTimePicker BackColor Disabilita la digitazione manuale?
- 14. Java interrompe la digitazione! Chi può spiegarlo?
- 15. Ricevi tutte dipendente che riferisce direttamente o indirettamente, a un dipendente, con livello di gerarchia senza
- 16. Digitazione implicita e TDD
- 17. Come funzionano la digitazione e la coercizione delegate/lambda?
- 18. Digitazione dinamica in C#
- 19. Che cos'è un esempio di digitazione anatra in Java?
- 20. Comunica la funzione dipendente nel ramo dell'istruzione condizionale che la condizione è vera
- 21. macro dipendente macro
- 22. Dipendente/dipendente Maven per il driver JDBC Redshift
- 23. Dipendente Walker: dll mancanti
- 24. Modello + Nome dipendente
- 25. Template dipendente typename
- 26. Posso migliorare questo metodo con la digitazione anatra?
- 27. EditText si blocca/non mostra il testo durante la digitazione
- 28. Tempo medio di pressione tra i tasti durante la digitazione
- 29. Disattivare gli avvisi di variabile inutilizzata Xcode durante la digitazione
- 30. Jquery: elenco a discesa dei filtri durante la digitazione
Sì. Questo è normalmente il modo in cui inizio tutto il mio apprendimento. – Nick
Quindi, cosa esattamente non capisci, ad es. l'articolo di Wikipedia? –
Bene, l'articolo si apre con i cubetti di lambda, che suona come un tipo di carne di pecora per me. Poi passa a discutere i sistemi λΠ2 e, non parlo alieno, ho saltato quella sezione. Poi ho letto del calcolo delle costruzioni induttive, che sembra incidentalmente avere poco a che fare con il calcolo, il trasferimento di calore o la costruzione. Dopo aver dato una tabella di comparazione linguistica, l'articolo termina, e sono rimasto più confuso di quando sono arrivato alla pagina. – Nick