Tutti questi termini - espressioni, valori e "classe" - sono concetti PL generali che non hanno legami specifici con Haskell e sono meglio compresi in un quadro più generale. Per mantenere le cose brevi, descriverò queste idee solo informalmente, sebbene sia importante rendersi conto che possono essere tutte rigorosamente definite all'interno di un quadro logico formale.
Espressioni
Le espressioni sono le unità di base della programmazione; in un certo senso, i programmi sono espressioni . Ecco alcuni esempi di espressioni (in un piccolo linguaggio inventato):
-
1 + 3 * 3
-
concat("hello", "world")
-
let x = pow(2, 2) in pow(x, x)
-
lambda x. x
Si noti che lambda x. x
(la funzione di identità) è un'espressione in questa lingua. Può essere usato in modo intercambiabile in qualsiasi contesto in cui è prevista un'espressione; per esempio, invece di 1 + 1
possiamo scrivere 1 + lambda x. x
*. In particolare, poiché gli argomenti di una funzione sono espressioni e le funzioni stesse sono espressioni, possiamo passare funzioni a funzioni come argomenti, ad esempio map(lambdax. x, [1, 2, 3])
.
Quindi, le funzioni di ordine superiore sono solo una conseguenza del trattamento di funzioni come espressioni. Al contrario, in una lingua che non lo fa, come C, tale espressione non è nemmeno un programma in quella lingua.
* Questo è valido secondo la sintassi astratta della lingua, ma il codice non controllerà il tipo. Maggiori informazioni su questo più tardi.
Dinamica e valori
Le espressioni sono statiche . È il lavoro delle dinamiche di un linguaggio per dirci come devono essere valutate le espressioni durante l'esecuzione. La dinamica (operativa) consiste in un insieme di semplici regole di transizione per trasformare una forma di espressione in un'altra. Ad esempio, le nostre dinamiche possono avere una regola che, informalmente, dice " n1 + 0
transizioni a n1
".
I valori in una lingua sono un sottoinsieme di espressioni che consideriamo essere pienamente valutate; scriviamo programmi (espressioni) per calcolare i valori. Le espressioni sopra riportate valgono per:
-
7
-
"hello world"
-
256
-
lambda x. x
Tangente: Dovrebbe essere il caso che un valore non possa passare a un'altra espressione, ma generalmente non vale l'opposto; ci sono alcune espressioni (ad esempio 7 + "hello world"
) che non possono essere valutate ulteriormente, ma non sono valori. Lo scopo di un sistema di tipi è evitare tali situazioni.
Quindi, per dichiarare che "le funzioni sono valori" dobbiamo a priori insistere sul fatto che le funzioni siano espressioni. Nella nostra lingua, consideriamo le funzioni come valori; quindi, lambda x. x
è un valore e map(lambda x. x, [1 2 3])
è un'espressione valida.
Per quanto ne so, sarebbe inutile creare una lingua in cui le funzioni siano espressioni ma non valori.