




























































































Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Paradigmi di Programmazione : lazy eager statico dinamico numeri di Church lamba calcolo call by value name reference - Sistemi dei Tipi : polimorfismo - Correttezza dei Programmi : logica di Hoare
Tipologia: Dispense
1 / 100
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!





























































































(dispense)
1 Introduzione
Su un argomento il dibattito politico era il piu acceso nel paese di Lilliput: se le uova alla coque andassero mangiate aprendone il guscio dal lato piccolo o dal grande. I sostenitori del lato piccolo si chiamavano “little-endians” (piccolapun- tisti) , i loro avversari “big-endians” (grossapuntisti). La diatriba sie riaperta nell’era del computer, dove little-endians sono i sostenitori delle architetture n cui la rappresentazione interna di un numero incomincia dalla cifra meno signi- ficativa (Intel e Digital) e big-endians i fautori della piu significativa (Motorola, IBM e SUN). A tutt’oggi non ce un vincitore: nel linguaggio C, il programma
int main(void) { int i = 1; char *c = &i; printf("%d", *c); }
stampa 1 su un’architettura little-endian, 0 su una big-endian. Dunque, alla domanda
“qual `e il significato di un programma?”
non e ragionevole rispondere “e l’effetto che esso produce quando eseguito su un computer”, perch´e... su quale computer? La Semantica e la disciplina che studia il significato di un linguaggio. Nel caso specifico dei linguaggi di programmazione la semantica puo essere defi- nita formalmente. Una tale definizione costituisce una specifica non ambigua del linguaggio, e dunque uno strumento per il progettista del linguaggio ed un riferimento per l’implementatore e per il programmatore. Una semantica for- male consente inoltre l’applicazione di strumenti matematici nello studio del linguaggio. In particolare essa consente:
e spessoe possibile generare automaticamente un compilatore o un interprete a partire da una specifica formale del linguaggio;Sono possibili divesi approcci alla definizione di equivalenza. Si pu`o, ad esempio, decidere di considerare equivalenti due programmi quando producono
lo stesso risultato, oppure quando e possibile sostituire l’uno con l’altro in ogni contesto di programma senza cosı produrre effetti “visibili”. In genere queste due definizioni non descrivono la stessa relazione.
Esercizio∗^ 1.1 Sono equivalenti le seguenti versoni (una ricorsiva e l’altra iterativa) della funzione fattoriale?
int fact (int n) { if (n==0) return 1; else return n * fact(n-1); }
int fact_iter (int n) { if (n==0) return 1; int i, result = 1; for (i=1; i<=n; i++) result = result * i; return result; }
Semantica statica
Gli oggetti matematici hanno un tipo. Questa nozione si trova alle fondamenta della matematica stessa: distinguendo tra insiemi “grandi” e “piccoli”, ad esem- pio, si evita di incappare in paradossi quale “l’insieme di tutti gli insiemi che non contengono se stessi come elemento”, una versione insiemistica del barbiere che rade tutti e soli coloro che non si radono da soli (chi radera il barbiere?!). Nel trattare i programmi come oggetti matematici, una semantica formale deve dunque assegnare un tipo ai termini del linguaggio. Per semantica statica di un linguaggio di programmazione si intende il suo sistema dei tipi, ovvero l’insieme delle regole che consentono di dare un tipo ad espressioni, comandi ed altri costrutti di programmazione. La determinazione dei tipi none un puro esercizio di virtuosismo matema- tico. Lo scopo principale di un sistema dei tipi `e infatti quello di prevenire l’occorrenza di errori durante l’esecuzione di un programma. Esempi di tali errori vanno dall’applicazione di funzioni ad argomenti inappropriati, al rife- rimento illegale della memoria, al tentativo di dividere un numero per zero. Nei diversi linguaggi di programmazione sono stati adottati approcci diversi a questo problema: vi sono linguaggi esplicitamente tipati come il Pascal o L’Al- gol, implicitamente tipati, come ML o Haskell, o non tipati affatto, come il LISP o l’Assembler. Per garantire la sicurezza, ovvero il non insorgere di errori “inaspettati”, linguaggi non tipati ad alto livello come il LISP prevedono un meccanismo di controllo dei tipi (type checking) dinamico (ovvero a tempo di esecuzione).
operazionale, ma mappando i termini del linguaggio su oggetti matematici: nu- meri, elementi di strutture algebriche e cosı via. Per esempio, se ρ = (x, 2)e l’ambiente semantico che associa alla variabile x il valore 2 (nota la differenza con la costante 2 della semantica operazionale), allora:
[[(4+x)-3]]ρ = [[4+x]]ρ − [[ 3 ]]ρ = 3
dove con [[t]]ρ si intende il significato di t nell’ambiente ρ. Questo esempio mostra la composizionalita della semantica denotazionale: il significato di un’espressione complessa come (4+x)-3e una funzione del significato delle sue componenti piu semplici: (4+x) e 3. In generale la semantica denotazionalee piu astratta di quella operazionale. Nel caso precedente, ad esempio, la seconda ci da una informazione sull’ordine di valutazione degli operandi che non risulta dalla prima.
Semantica assiomatica. Il significato di un programma p e determinato nell’ambito di una teoria assiomatica dall’insieme delle proposizioni vere per p. In generale, questa semantica consente un approccio “meccanico” alla dimo- strazione formale di proprieta di programmi. Ad esempio, data una opportuna assiomatizzazione degli operatori if, for, :=, e cosı via,e possibile derivare formalmente la seguente proposizione:
{n ≥ 0 } fact(n); {res = n!}
dove {A} p {B} viene letta: “se il programma p, eseguito in uno stato che soddi- sfa la proprieta A, termina, allora lo stato da esso prodotto soddisfa la proprieta B”.
Le caratteristiche di un linguaggio
Nei manuali di programmazione il significato dei costrutti di un linguaggio viene di solito descritto facendo uso di nozioni semantiche quali quella di variabile, istruzione, sottoprogramma e cosı via. Di ciascuno di questi oggettie possibile specificare degli attributi. Ad esempio:
Valori di tipo appropriato possono essere associati agli attributi delle entita di un programma tanto durante la compilazione quanto durante l’esecuzione. L’associazione di un valore ad uno o piu attributi di una entita si chiama binding (legame). Un fattore importante nell’analisi di un linguaggio di programmazionee il tempo di binding. Attributi diversi di una stessa entita possono essere legati in tempi diversi, ed un legame puo essere modificato durante l’esecuzione. Ad esempio: una variabile puo essere legata al suo tipo a tempo di compilazione ed al suo valore a tempo di esecuzione. Un legame si dice statico see stabilito prima dell’esecuzione e non pu`o essere cambiato in seguito, dinamico altrimenti. Ecco alcuni esempi di binding statico e dinamico
e legato al momento della defini- zione del linguaggio, mentre in Pascal il tipo integer puo essere ridefinito dal programmatore, e quindi legato alla sua rappresentazione a tempo di compilazione.e corretta solo se, al momento dell’esecuzione, B e C contengono valori numerici, o sono matrici con lo stesso numero di dimensioni e grandezza. In generale, linguaggi in cui il legame di tipoe statico (Fortran, Pascal, Modula 2, Ada ecc.) sono anche detti fortemente tipati; quelli con legame dinamico (LISP, Snobol, APL, ecc.) sono anche detti non tipati.
e tipicamente dinamico. Una variabile con legame statico al valoree una costante simbolica (per distinguerla dalle costanti “letterali”, literal). In Pascal:const pi = 3.14; circonferenza = 2 * pi * raggio;
In Pascal una costante viene tradotta dal compilatore nel suo valore. Le costanti dell’Algol 69 sono piu dinamiche: il loro valore viene determina- to a tempo di esecuzione, valutando una espressione che puo contenere variabili. In modo simile le variabili di tipo final di Java.
3 Struttura e rappresentazione
How much is two? Paul Halmos - Naive Set Theory
Per sintassi di un linguaggo di programmazione si intende generalmente un insieme di regole formali che definiscono le stringhe (ovvero le sequenze finite di simboli) del linguaggio. La sintassi e spesso definita usando la notazione BNF, ovvero mediante una grammatica libera dal contesto: il linguaggioe l’insieme delle stringhe di simboli terminali generabili mediante una derivazione, ovvero applicando le produzioni della grammatica. Va notato che le grammatiche libere dal contesto non sono generalmente adeguate ad esprimere vincoli sintattici quali la dichiarazione delle variabili prima dell’uso o la correttezza di una espressione dal punto di vista dei tipi. Una derivazione getta luce sulla struttura di una stringa, ovvero determina un albero sintattico. L’informazione sulla struttura, come ad esempio la precedenza da assegnare agli operatori nell’interpretazione di una espressione aritmetica, e necessaria per associare un significato agli elementi di un linguaggio (semantica). Una grammatica si dice ambigua se esiste piu di un albero sintattico per una stessa stringa. (Per una introduzione alle nozioni di grammatica, derivazione, albero sintattico... vd. [HMU03].) Affinch´e un compilatore o un interprete possano riconoscere le stringhe di un linguaggio, e necessario che questo sia definito da una grammatica non am- bigua. Esistono tecniche per disambiguare una grammatica o per trasformarne le produzioni in modo da rendere piu efficiente il riconoscimento, al costo pero di complicare, a volte in modo drammatico, gli alberi sintattici con struttura di scarsa rilevanza semantica. Per ovviare a questo inconveniente si ricorre, nello studio della semantica, all’uso della sintassi astratta. Come vedremo, la sintassi astratta none altro che una definizione induttiva. Il lettore ha probabilmente familiarita con l’induzione matematica, una tecnica per la dimostrazione di proprieta sui numeri naturali, e con definizioni induttive, quale ad esempio quella della funzione fattoriale. In questa sezione mostreremo che tecnica per definire funzioni o dimostrare proprieta sui numeri naturali, puo essere generalizzata ed applicata ad altri oggetti quali ad esempio gli alberi o, appunto, i termini di un linguaggio di programmazione. Il risultato della nostra investigazione sara l’ induzione strutturale, un principio generale di cui l’induzione matematica rappresenta un caso particolare. Iniziamo da cio che conosciamo: i numeri naturali.
I numeri naturali
Nel 1894 il matematico italiano Giuseppe Peano (1858 - 1932) propose una presentazione assiomatica dell’insieme N dei numeri naturali:
per induzione (ovvero per casi, uno per lo zero ed uno per il successore), cosa che nessuno delle altre proposte ci consente di fare. Consideriamo infatti l’usuale definizione della funzione fattoriale:
fact (0) = 1 fact (succ (n)) = succ (n) ∗ fact (n).
Se, violando il quinto assioma, scegliamo N> come modello dei naturali questa definizione risulta incompleta, perch´e non dice quanto vale fact (♥). Analoga- mente, la seguente definizione del predicato “essere pari”:
is even (0) = true is even (succ (n)) = not (is even (n))
darebbe risultati contraddittori se, in barba al quarto assioma, adottassimo il secondo modello dell’alieno, dove succ (1) = 1; dalle equazioni conseguirebbe infatti true = false. Considerazioni analoghe valgono per le dimostrazioni. Considerate infatti lo schema dell’induzione matematica:
P (0) P (n) ⇒ P (n + 1)) ∀ n. P (n)
Volendo usare questo schema per dimostrare, ad esempio, che tutti i naturali sono numeri primi, dovremmo scegliere come P (n) la proposizione “n e un numero primo”. Ora, se adottassimo N> come modello dei naturali, questo schema ci consentirebbe di dimostrare erroneamente che nessun elemento di N>,e uguale a ♥, incluso ahim´e ♥ stesso (si scelga come P (n) la proposizione “n e diverso da ♥”). Va notato che lo schema dell’induzione matematica altro none che il quinto assioma di Peano (che viene infatti chiamato principio di induzione) espresso usando la nozione di predicato al posto di quella di sottoinsieme. Infatti, un predicato P sui numeri naturali puo essere visto come un insieme SP ⊆ N , ovvero quel sottoinsieme dei numeri naturali che soddisfano la proprieta espressa dal predicato. L’assioma 5 ci dice che se 0 ∈ Sp (ovvero, se vale P (0)) ed inoltre se n ∈ Sp implica succ(n) ∈ SP (ovvero P (n) implica P (n + 1)), allora SP = N (ovvero, per ogni n ∈ N vale P (n)).
Torniamo ora alla domanda iniziale: quale tra gli infiniti modelli degli as- siomi di Peano e “il vero” insieme dei naturali? La rispostae: non importa, dato che tutti i modelli sono fra loro isomorfi. Se, insieme a von Neumann, l’alieno preferisce ℵ, faccia pure: come chiariremo ora, `e solo una faccenda di rappresentazione.
L’insieme N dei numeri naturali, con l’operazione di somma e lo 0, elemento neutro dell’operazione, formano un’algebra detta monoide. La somma lavora su
due argomenti e viene percio detta binaria, o di arieta 2. Questo si indica sim- bolicamente attaverso una segnatura: N × N → N. Altre strutture algebriche sono, ad esempio, i gruppi. Il gruppo Z degli interi possiede, fra le altre, un’o- perazione Z → Z, di arieta 1, che associa ad ogni intero z il suo complemento −z. Vi sono poi strutture algebriche le cui operazioni usano (anche) argome- ni esterni all’algebra stessa: sull’algebra L delle liste di interi, ad esempio,e definita un’operazione cons : L × Z → L che aggiunge un intero ad una lista: cons (〈 2 , 5 〉, 7) = 〈 7 , 2 , 5 〉. In questo caso si dice che l’operazione e parametrica in Z. Le definizioni che seguono consentono di trattare in modo uniforme gli esempi fin qui riportati. Una segnatura algebricae costituita da un insieme I di nomi di funzione e, per ogni i ∈ I, un numero αi ≥ 0 ed una sequenza Ki = 〈Ki 1 ,... Kini 〉 di insiemi, i domini degli eventuali parametri esterni dell’operazione. Indichiamo con |Ki| la lunghezza della sequenza Ki. Il numero αi rappresenta, a meno di parametri esterni, l’arieta di i, che sara dunque αi + |Ki|. Per brevita di notazione scriveremo semplicemente I per indicare una segnatura. Abuseremo anche della notazione denotando con Ki l’insieme Ki 1 × · · · × Kini , mentre An indica come sempre il prodotto cartesiano di un insieme A per se stesso n volte. Un’algebra (A, γ) di segnatura Ie una struttura matematica costituita da un insieme A, chiamato carrier o insieme sottostante dell’algebra, ed una famiglia γ = {γi}i∈I di funzioni
γi : Aαi^ × Ki → A
chiamate operazioni fondamentali dell’algebra^1. Quando il contesto ci con- sentira di farlo senza ambiguita, useremo semplicemente A o γ per indicare un’algebra (A, γ). La somma, nel monoide dei naturali, e un’operazione di arieta 2 senza pa- rametri esterni (α+ = 2), mentre cons, nell’algebra delle liste, e un’operazione di arieta 2 con un parametro esterno (αcons = 1). Ora, cosa succede se, per qualche operazione i della segnatura, si ha αi = 0 (e, ad esempio, non vi sono parametri esterni)? In altre parole: cos’e una funzione nullaria, cioe con arieta 0? Consideriamo la coppia (7, 3). Essae un elemento dell’insieme N × N = N 2. La tripla (9, 2 , 6) `e un elemento di N × N × N = N 3. Dovremo allora convenire che () sia un elemento dell’insieme N 0 , l’unico! Dunque, indicando con 1 questo insieme, in analogia col mondo dei numeri dove n^0 = 1, si ha:
N 0 = {()} = 1.
Una funzione nullaria su un insieme A avra dunque segnatura 1 → A. Per semplicita assumeremo che, per ogni insieme X, l’equazione 1 × X = X valga in senso stretto. Dunque un’operazione γi di un’algebra A con αi = 0 e, ad esempio, un solo parametro esterno K avr`a segnatura K → A e non 1 ×K → A.
(^1) Algebre con parametri esterni sono dette eterogenee. Nei libri di algebra (vedi ad esempio [Lan93, BS81]) si considerano in genere operazioni senza parametri esterni. Questi rendo- no tutto un po’ pi`u complicato, ma sono qui necessari per trattare con strumenti algebrici strutture dati quali liste o alberi o, come vedremo oltre, i termini di una sintassi astratta.
Le γi sono chiamate costruttori di A. Un costruttore γi `e chiamato base se αi = 0. (^2)
Esercizio∗^ 3.4 Trovare un insieme di costruttori per i booleani {true, false}. La funzione not, lei da sola, soddisfa i requisiti? (^2)
Esercizio 3.5 Dimostrare che ogni algebra induttiva non vuota ha almeno un costruttore base. Dimostrare che ogni algebra induttiva non vuota con un costruttore non base `e necessariamente infinita. (^2)
Teorema 3.1 Sia A un’algebra induttiva. Per ogni algebra B con stessa segna- tura esiste un unico omomorfismo A → B.
Corollario 3.1 Due algebre induttive A e B con la stessa segnatura sono ne- cessariamente isomorfe.
Dimostrazione. Se f : A → B e g : B → A sono i due omomorfismi ottenuti applicando il Teorema 3.1 rispettivamente ad A e B, gli omomorfismi composti g · f : A → A e f · g : B → B devono coincidere necessariamente (per la condizione di unicita) con le identita, da cui l’isomorfismo. (^2)
Nella sezione 11.1 mostreremo che il teorema 3.1 costituisce il fondamen- to dello schema a clausole che si usa abitualmente in matematica per definire funzioni su insiemi induttivi, e che il linguaggio SML adotta per definire fun- zioni su datatype (vedi sezione 3.3). Il suo corollario, noto nella sua versione categoriale come lemma di Lambek , gioca invece un ruolo importante in que- sta sezione, perch´e ci consente di distinguere fra struttura e rappresentazione. Mentre in informatica l’implementazione che scegliamo per un tipo di dato puo avere un forte impatto sull’efficienza degli algoritmi che manipolano i dati, in matematica si tende a considerare irrilevante cio che distingue oggetti isomorfi. Il corollario 3.1 ci dice dunque che cio che in un insieme induttivoe matemati- camente rilevante e la struttura, chee data dalla sua segnatura; tutto il resto `e rappresentazione.
Torniamo all’insieme N dei numeri naturali. I primi due assiomi di Peano ci danno una segnatura algebrica:
0 : 1 → N succ : N → N.
Gli altri assiomi di Peano, 3, 4 e 5, corrispondono esattamente alle condizioni (rispettivamente) 2, 1 e 3 della Definizione 3.1. Questo ci dice che N e un’algebra induttiva, e cio `e quanto basta per definire (induttivamente) funzioni e dimo- strare teoremi (per induzione). Poi, per il lemma di Lambek, fa poca differenza rappresentare N come { 0 , 1 ,... } o come { { }, {{ }},... }.
Esercizio 3.6 Mostrare che esiste un isomorfismo algebrico tra l’insieme dei numeri naturali e l’insieme P = { 0 , 2 , 4 ,... } dei numeri pari, dove 0P = 0 e succP (n) = n + 2. (^2)
Esercizio 3.7 La funzione f : N> → ℵ tale che f (♥) = 0ℵ, f (0) = 1ℵ, f (1) = (^2) ℵ e biunivoca ma none un isomorfismo di algebre. Perch´e? (^2)
Esercizio 3.8 Scesi sulla terra, gli alieni ci parlano di algebra universale e, in particolare, di due insiemi, 2 e 4 , definiti induttivamente da costruttori con le seguenti segnature. C’`e qualcosa di simile, chiedono, sulla Terra?
2
Vediamo ora un altro esempio di algebra induttiva, quella degli alberi binari. Traiamo ispirazione dalla definizione induttiva di N : un numero naturale e zero, oppure il successore di un numero naturale. Analogamente, un albero binarioe una foglia, oppure una radice con un sottoalbero (binario) destro ed uno sinistro. Ecco due esempi di alberi binari ed un non-esempio:
Questi sono solo disegni. Per spiegare ad un alieno la nozione di albero binario, si potrebbe dare la seguente definizione ricorsiva: l’insieme B-trees degli alberi binari `e quello definito induttivamente da due costruttori con la seguente segnatura: leaf : 1 → B-trees branch : B-trees × B-trees → B-trees
(... sı,e proprio 4 !). L’alieno e ora libero di immaginare gli alberi come meglio crede e di scegliere l’interpretazione che preferisce per i simboli leaf e branch: il lemma di Lambek garantise che, qualunque sia la scelta, la sua rappresentazione sara isomorfa alla nostra. Ora possiamo usare lo schema induttivo per definire funzioni su B-trees. Nella sezione 11.1 torneremo sul fondamento di questo schema; qui ci limiteremo a metterlo in pratica per definire la funzione leaves,
Alberi come grafi Nella teoria dei grafi un albero e un grafo non orientato nel quale due vertici sono connessi da uno ed un solo cammino. Un alberoe definito dunque in termini di una coppia (V, E) dove V e un insieme di vertici (assumia- molo finito) ed Ee un insieme di archi con particolari proprieta. In particolare, un albero radicatoe un albero nel quale ad un vertice viene conferito uno speciale status di “radice”. Da questa investitura deriva un orientamento naturale degli archi (che consiste nell’allontanarsi dalla race) ed una relazione padre-figlio. Se aggiungiamo poi il vincolo che ogni padre abbia esattamente due figli, ottenia- mo gli alberi binari. Che rapporto c’e fra gli alberi binari cosı ottenuti e gli elementi di B-trees? Ebbene: ne sono la versione commutativa! Notiamo infatti che mentre, per l’iniettivita dei costruttori, branch (t 1 , t 2 ) 6 = branch (t 2 , t 1 ) per t 1 6 = t 2 , negli alberi-grafo non c’e alcun ordinamento fra i figli di un nodo, e non ha dunque senso parlare di sottoalbero destro e sinistro. Per ottenere gli alberi- grafo (binari), dobbiamo dunque quozientare B-trees rispetto alla congruenza indotta dall’equazione branch (t 1 , t 2 ) = branch (t 2 , t 1 ). Gli alberi-grafo binari corrispondono allora alle classi di equivalenza indotte su B-trees dalla relazione che esprime la commutativita di branch. Quella degli “alberi commutativi”e un esempio di teoria algebrica, ovvero una teoria i cui assiomi sono equazioni. Altre teorie algebriche sono quella dei monoidi, dei gruppi, degli anelli, dove le equazioni impongono, ad esempio, l’associativit`a della moltiplicazione. Anche per algebre di questo tipo esiste un equivalente del teorema 3.1, ma questo ci porta oltre i limiti della nostra trattazione.
Sintassi Astratta
Sia L il linguaggio (un insieme di stringhe) generato dalla seguente grammatica.
Exp ::= 0 | 1 |... | Exp + Exp | Exp * Exp
Supponiamo di voler definire una funzione eval : L → N che valuta le espressioni del linguaggio. Se e 1 ed e 2 sono stringhe, indichiamo con e 1 +e 2 la stringa ottenuta concatenando le tre stringhe e 1 , " + " ed e 2. Ad esempio, "4" + "7" = "4 + 7".
eval ( 0 ) = 0 eval ( 1 ) = 1
... eval (e 1 + e 2 ) = eval (e 1 ) + eval (e 2 ) eval (e 1 * e 2 ) = eval (e 1 ) ∗ eval (e 2 )
Attenzione alla differenza tra 0 e 0, tra + e +, e cos`ı via. Ora, quanto fa eval (3 * 2 + 1)? Dipende:
eval (3 * 2 + 1) = eval ( 3 ) ∗ eval (2 + 1) = 3 ∗ 3 = 9, oppure eval (3 * 2 + 1) = eval (3 * 2) + eval ( 1 ) = 6 + 1 = 7.
Cio che abbiamo tentato di faree procedere per casi, cosı come avevamo fatto per fact o per leaves nelle sezioni precedenti. Cio che rende pero ac- cettabile la definizione di fact ma non quella di evale che la prima applica uno schema induttivo di definizione su un insieme definito induttivamente (N ), mentre la seconda tenta di applicare lo stesso schema ad un insieme (L) che induttivo non e. In effetti, ciascuna produzione della grammatica definisce un operatore su L. Ad esempio, Exp ::= Exp + Exp definisce l’operatore binario Plus : L × L → L tale che Plus ("3", "2 + 1") = "3 + 2 + 1". Analogamen- te, per il prodotto: Times ("3", "2 + 1") = "3 * 2 + 1", e cosı via. Questi operatori sintattici tuttavia non sono i costruttori del linguaggio, ovvero non definiscono L induttivamente. In particolare Plus e Times non hanno imma- gini disgiunte, visto che Times ("3", "2 + 1") = Plus ("3 * 2", "1"), da cui l’ambiguit`a nella definizione di eval.
La sintassi astratta di un linguaggio e una definizione induttiva di un insieme T di termini. Per esempio, la sintassi astratta del linguaggio delle espressionie data dalla seguente segnatura:
zero : 1 → T one : 1 → T
...... plus : T × T → T times : T × T → T
Ora la domanda `e: come sappiamo che un’algebra induttiva con questa segnatura esiste? La seguente costruzione ci assicura in tal senso.
Data una segnatura I, definiamo un’algebra (T, τ ) su I:
T (^) n+1 = Tn ∪ { (i, t 1 ,... , tαi , k 1 ,... , k|Ki|) | i ∈ I, tj ∈ T (^) n, per j = 1... αi, e kl ∈ Kl, l = 1... |Ki| } T =
n≥ 0 T^ n
Le operazioni τi sono definite come segue:
τi(t 1 ,... , tn, k 1 ,... , kn) = (i, t 1 ,... , tn, k 1 ,... , km).
Va notato che, in accordo con quanto visto nell’esercizio 3.5, se non vi sono costruttori base in τ , T `e vuoto. Gli elementi di T sono chiamati termini, e T algebra dei termini su I.
Teorema 3.2 (T, α) `e un’algebra induttiva.
Torniamo alla nostra grammatica per le esperssioni. Abbiamo visto che essa definisce un’algebra (non induttiva) sul linguaggio L. Il teorema 3.2 ci d`a la sua