Esercizio

Basandosi sul seguente tipo di dato:

datatype espressione = costante    of int
                     | somma       of espressione * espressione
                     | sottrazione of espressione * espressione
                     | prodotto    of espressione * espressione
                     | divisione   of espressione * espressione;
    
scrivere una funzione Standard ML, chiamata eval, che ha tipo espressione -> int.

Come suggerito dal nome, eval valuta l'espressione ricevuta come argomento, ritornando un intero che indica il risultato finale della valutazione.

La funzione eval deve essere definita in un file .sml separato dalla definizione del tipo di dato espressione. Si consegni il file .sml contenente la definizione di eval.

Possibile Soluzione

Questa e' una possibile soluzione.

Inoltre...

E' possibile definire una funzione semplifica che semplifica un'espressione ricevuta come argomento. La differenza fra semplifica ed eval e' quindi che semplifica ha tipo espressione -> espressione. Quindi, semplifica puo' essere definita basandosi su eval (e magari "nascondendo" eval tramite un costrutto local). Questo approccio puo' essere implementato anche in modo molto piu' semplice.

E' pero' anche possibile definire semplifica per via ricorsiva, senza riferimenti ad eval.

Altro Esercizio

Basandosi sul tipo di dato espressione e la funzione eval definiti come segue:

datatype espressione = costante    of int
                     | somma       of espressione * espressione
                     | sottrazione of espressione * espressione
                     | prodotto    of espressione * espressione
                     | divisione of espressione * espressione;

val rec eval = fn costante    n        => n
                | somma       (a1, a2) => (eval a1) + (eval a2)
                | sottrazione (a1, a2) => (eval a1) - (eval a2)
                | prodotto    (a1, a2) => (eval a1) * (eval a2)
                | divisione   (a1, a2) => (eval a1) div (eval a2);
       
il tipo espressione puo' essere esteso come segue per supporare il concetto di variabile:
datatype espressione = costante    of int
                     | variabile   of string
                     | somma       of espressione * espressione
                     | sottrazione of espressione * espressione
                     | prodotto    of espressione * espressione
                     | divisione   of espressione * espressione
                     | var         of string      * espressione * espressione;
       

Si riscriva la funzione eval per supportare i due nuovi costruttori variabile e var. variabile x, con x di tipo stringa, e' valutata al valore della variabile di nome x (per fare questo, eval deve cercare nell'ambiente un legame fra tale nome ed un valore). var (x, e1, e2) e' valutata al valore di e2 dopo aver assegnato ad x il valore di e1.

Per poter valutare correttamente variabile e var, eval deve quindi ricevere come argomento l'ambiente in cui valutare le variabili. Tale ambiente puo' essere rappresentato come una lista di coppie (stringa, intero) ed avra' quindi tipo (string * int) list.

La funzione eval deve quindi avere tipo (string * int) list -> espressione -> int.

La funzione eval deve essere definita in un file .sml separato dalla definizione del tipo di dato espressione. Si consegni il file .sml contenente la definizione di eval.

Possibile Soluzione

Questa e' una possibile soluzione. Si noti che in questa soluzione la funzione cerca viene definita come visibile a tutti, mentre sarebbe piu' opportuno renderla locale a eval usando un costrutto let o local.