Questa sezione e' composta da tre parti: ESERCIZI LAMBDA-CALCOLO, ESERCIZI HASKELL e ESERCIZI PROGRAMMAZIONE HASKELL





ESERCIZI LAMBDA CALCULUS



Esercizio 0
  • Cosa si intende per "programma" nel contesto dei linguaggi di programmazione funzionale?
  • In cosa consiste l'"esecuzione" di un programma in un linguaggio funzionale?
  • Elencare alcuni concetti tipici della programmazione imperativa che perdono completamente di significato in quella funzionale.
  • Cos'e' un Modello Computazionale?
  • Cosa si intende per "astrazione funzionale" e come questa viene formalizzata nel lambda-calcolo?
  • Cosa si intende per "currificazione" e quali sono i possibili vantaggi del suo utilizzo.
  • Cos'e' la relazione di alfa-convertibilita' tra termini?
    Esercizio 1
    Dato il seguente termine, cerchiare le sue variabili libere e collegare, utilizzando delle frecce, le sue variabili legate con i lambda relativi.

    λz.( ((λx.λx.yx)x)(vλz.λw.v) )

  • Soluzione.

    Esercizio 2


    Descrivere sinteticamente alcuni svantaggi dei linguaggi di programmazione funzionali.


  • Soluzione.

    Esercizio 3


    Ridenominare alcune variabili legate nel seguente termine, in modo che non ci siano due lambda che leghino variabili con lo stesso nome.

    (λxxx.(zλz.x))(xλy.(y(λy.z)yy))

  • Soluzione.

    Esercizio 4


    Ricopiare il seguente termine sottolineando le variabili libere e mettendo un cerchietto intorno a quelle legate:

    (λx.(z(λz.((xyz)x))zx))x(λx.((λy.yy)(λz.zz)))

  • Soluzione.

    Esercizio 5


    Rinominare le variabili legate nel seguente termine in modo che non ci siano due variabili legate con lo stesso nome

    x(λx.((λx.x)x))


    Esercizio 6


    Fornire un lambda-termine che contenga variabili con nome x, y e z ed in cui ci siano occorrenze sia legate che libere di variabili con tali nomi.

  • Soluzione.
    Esercizio 7


    Riscrivere il seguente termine utilizzando il minimo numero di parentesi secondo le convenzioni sintattiche

    ((xy)(λy.(λz.(z(xy)))))

  • Soluzione.
    Esercizio 8

    Supponendo di non utilizzare le convenzioni sintattiche sulle parentesi, riscrivere il seguente termine inserendo tutte le possibili parentesi.

    (λxyz.xy(xz))λxy.x

  • Soluzione.
    Esercizio 9

    Definire la nozione di "Currificazione". E' una nozione applicabile al lambda-calcolo? perche'?


  • Soluzione.
    Esercizio 10

    Fornire la definizione formale di sostituzione.
    Esercizio 11

    Qual e' la condizione che deve essere soddisfatta affinche' sia possibile applicare una sostituzione senza produrre "effetti indesiderati"?
    Esercizio 12

    Eseguire le seguenti sostituzioni
    Esercizio 13

    Eseguire le seguenti sostituzioni:
    Esercizio 14

    Eseguire la seguente sostituzione:

    z(λy.wy)λz.((λx.yx)xz) [yz/x,yz/w]


    Esercizio 15

    Dire qual e' il risultato della seguente sostituzione:

    ((λy.xy)(λz.y(λy.x)))[xyz/x]


    Esercizio 16

    Dire qual e' il risultato della seguente sostituzione:

    ((λy.yy)y(λy.y(λy.y)))[λy.zy/y]


    Esercizio 17

    Qual e' il risultato delle seguenti sostituzioni?
    Esercizio 18

    Qual e' il risultato della seguente sostituzione?

    ((λw.(xw))(λy.(yx)))[λx.(w(xy))/x]


    Esercizio 19

    Eseguire le seguenti sostituzioni:
    Esercizio 20

    Qual e' il risultato delle seguenti sostituzioni? Quali sono gli insiemi delle variabili legate e libere dei termini ottenuti?

    Esercizio 21

    Qual e' la condizione che deve essere necessariamente soddisfatta per poter correttamente effettuare una sostituzione M[N/x] ? Perche' tale condizione e' necessaria?


    Esercizio 22

    Eseguire le seguenti sostituzioni:
    Esercizio 23
    Fornire la definizione esplicita dell'insieme di tutti i lambda-termini in forma normale (descrivere, in modo ricorsivo, la forma che deve avere un termine in forma normale).

  • Soluzione.
    Esercizio 23.5
    Qual e', se esiste, la forma normale del seguente termine? (\x.yy)((\z.z)x))
    Esercizio 24
    Trovare la forma normale di

    (λxxxx.xx)(λx.xx)(λx.x)y((λx.x)x)

  • Soluzione.
    Esercizio 25
    Trovare la forma normale di

    (λx.((λy.z)x))((λx.xx)(λx.xx))


    Esercizio 26
    Trovare la forma normale di

    (λx.((λy.z)x))((λx.xx)(λx.xx))

    Dire inoltre se questo termine e' fortemente normalizzabile.


    Esercizio 27
    Qual e' la formal normale del seguente termine?

    ((λw.(xw))(λy.(yx)))[λx.(w(xy))/x]

    Qual e' l'insieme delle sue variabili libere? e quale quello delle sue variabili legate?

    Esercizio 28
    Fornire un lambda-termine normalizzabile il cui insieme di variabili libere sia {x, y}, e tale che l'insieme delle variabili libere della sua forma normale sia {x, y, z}.
  • Soluzione.

    Esercizio 29
    Fornire un lambda termine che si riduca a forma normale in due passi di riduzione. Inoltre tale termine deve avere {x, y, z} come insieme di variabili libere, mentre le variabili libere della sua forma normale dovranno essere {x, y}.
  • Soluzione.

    Esercizio 30
    Portare in forma normale, se esiste, il seguente lambda-termine:

    (λx.((λz.zwz)(((λxyx.y)(λx.y)(λy.x))((λx.xx)(λy.yyy)))))t



  • Soluzione.

    Esercizio 31
    Qual e' la forma normale, se esiste, del seguente lambda-termine?

    (λx.xxy)(λxy.xyy)

  • Soluzione.

    Esercizio 32
    Dire in quale caso e' possibile avere un lambda-termine con piu' di una forma normale.
  • Soluzione.

    Esercizio 33
    Qual e' la forma normale, se esiste, del seguente lambda-termine?

    (λxy.yx)(λxy.x(yy))(λx.xz(λy.yy))

  • Soluzione.

    Esercizio 34
    Qual e' la forma normale del seguente termine?

    ((λw.(xw))(λy.(yx)))[λx.(w(xy))/x]

    Qual e' l'insieme delle sue variabili libere? e quale quello delle sue variabili legate?


    Esercizio 35
    Dire se il seguente termine possiede forma normale ed eventualmente fornirla insieme ai vari passi di riduzione:

    (λxxx.((λxx.x)(xx)(λx.x)))x(xx)


  • Soluzione.

    Esercizio 36
    Dire in quale caso e' possibile avere un lambda-termine con una sola forma normale.
  • Soluzione.

    Esercizio 37

    Esercizio 38
    Dimostrare che se un termine M contiene Omega ( (λx.xx)(λx.xx) ) come sottotermine proprio, allora non e' normalizzabile (non possiede forma normale).
  • Soluzione.

    Esercizio 39
    Enunciare e dimostrare il Corollario di Unicita' della forma normale.

    Esercizio 40
    Fornire la definizione di alfa-conversione. Qual e' il motivo per introdurre tale nozione nel lambda-calcolo?

    Esercizio 41


    Esercizio 42


    Esercizio 43
    Fornire un lambda termine che sia normalizzabile, ma a partire dal quale esiste anche una sequenza infinita di beta-riduzioni.

    Esercizio 44
    Cos'e' una strategia di riduzione?

    Esercizio 45
    Cosa si intende per strategia di riduzione Call-by-value?

    Esercizio 46


    Esercizio 47
    Dare la definizione di strategia di riduzione, strategia di riduzione call-by-value, strategia di riduzione call-by-name, strategia leftmost-outermost.
    La strategia leftmost-outermost e' call-by-value o call-by-name ?

    Esercizio 48


    Esercizio 49


    Esercizio 50-67


    Esercizio 68
    Dimostrare che se P -->beta Q allora FV(Q) e' un sottoinsieme di FV(P).

  • Soluzione.

    Esercizio 69


    Esercizio 70
    Spiegare perche' talvolta, prima di eseguire una beta-riduzione, occorra rinominare le variabili legate (della lambda astrazione). In tali casi, si riuscirebbero ad evitare problemi se si operasse invece sulle variabili dell'argomento della beta riduzione? Motivare.

    Esercizio 71
    Trovare tre termini M,P e Q, tali che M contiene x e y tra le sue variabili libere e tali che M[P/x,Q/y] sia diverso da M[P/x][Q/y]

    Esercizio 72


    Esercizio 73

    Dimostrare che il lambda-termine

    (λx.xxx)(λx.xxx)

    non e' normalizzabile.

  • Soluzione.



    Esercizio 74



    Esercizio 75

    Enunciare il Teorema di Confluenza del λ-calcolo ed utilizzarlo per dimostrare la proprieta' di unicita' della forma normale.




    Esercizio 76

    Fornire la definizione formale di sostituzione per il lambda-calcolo.
    Trovare poi tre termini M,P e Q, tali che M contenga x e y tra le sue variabili libere e tali che M[P/x,Q/y] sia diverso da M[P/x][Q/y]
  • Soluzione.



    Esercizio 77

    Definire formalmente la nozione di sostituzione nel λ-calcolo.
    Effettuare la seguente sostituzione e ridurre il termine ottenuto, se possibile, in forma normale.
    ((λw.(xw))(λy.(yx)))[λx.(w(xy))/x]

  • Soluzione.








    ESERCIZI HASKELL





    Esercizio 1


  • Soluzione

    Esercizio 2

    Supponete di aver definito una funzione Haskell di nome funct.
    Dire cosa fa il sistema se si scrive:
                                     :type  funct
    
    Dire cosa avrebbe fatto il sistema se prima della definizione di funct uno avesse scritto:
                                     funct :: [Int] -> Bool
    

  • Soluzione

    Esercizio 3

    Definire in HASKELL il tipo di dato astratto Albero binario etichettato con etichette numeriche.

  • Soluzione

    Esercizio 4

    Definire in HASKELL il tipo di dato astratto Albero ternario senza etichette.

  • Soluzione

    Esercizio 5

    Definire in Haskell il tipo di dato Albero ternario etichettato. Discutere brevemente la soluzione proposta.

  • Soluzione

    Esercizio 6




    Esercizio 7

    Supponendo che non sia predefinito, definire in HASKELL il tipo di dato astratto Lista di Interi. E' possibile definire il tipo di dato Lista di elementi qualsiasi?

  • Soluzione

    Esercizio 8




    Esercizio 9

    La sonda Spirit ha trovato che su Marte esistono i Loffioni.
    Un Loffione puo' essere un Gangarone oppure un Sarrapone, oppure una sequenza finita di Purpuroni. Un Purpurone e' formato da un Gangarone e un Sarrapone. In natura il numero di sarraponi e' infinito, invece esistono solo due Gangaroni, il GangaroneA e il GangaroneB.
    Definire in Haskell il tipo di dato astratto Loffione che possa permettere di scrivere programmi Haskell che simulino esperimenti virtuali sui Loffioni.

  • Soluzione

    Esercizio 10

    Le seguente definizioni HASKELL
    f n = n:(f(n+1))
    nums = f 0
    
    corrispondono, in SCHEME, a
    (define (f n)  (cons n (f (+ n 1))))
    (define nums (f 0))
    
    Che cosa "dovrebbe" fare f? e cosa e' nums?
    Perche' in Haskell possiamo utilizzare f e nums (fornire possibilmente un esempio di uso), mentre in SCHEME non ci possiamo fare in pratica niente?
    Perche' comunque, anche se poi non ci possiamo fare un fico secco, SCHEME permette lo stesso di definire la funzione f senza darci problemi?

  • Soluzione

    Esercizio 11

    Presa la seguente definizione di tipo in HASKELL
    	data Pirimpo = Pompero Int | Zumpo Pirimpo [Int]
    	
    scrivere delle definizioni Scheme che permettano di utilizzare (per qual che e' possibile in Scheme) il tipo di dato Pirimpo.

  • Soluzione

    Esercizio 12
    Gli Yunz sono esseri magici che nella contea di Hargaar vengono usati dagli studenti per passare gli esami.
    Uno Yunz puo'  venire generato dicendo due numeri qualsiasi mentre si effettua l'incantesimo del mago Frunz su due Yunz. Il nanetto Yor e' uno Yunz.

    Esercizio 13

    Dire brevemente cosa fa' l'interprete HASKELL quando scriviamo qualcosa del genere:
    	funct :: [Int] -> Bool
    		
    	funct ls = BODY
    

    Esercizio 14

  • Soluzione

    Esercizio 14


    Esercizio 15


    Esercizio 16


    Esercizio 17
    Esercizio 18


    Esercizio 19
    Si consideri la seguente funzione Haskell:
    myPenultimo (x) |  (length x)==1  = x
                    |  (length x)==2  = head x
                    |  otherwise      = myPenultimo(tail x)
    
    L'interprete restituisce il seguente errore
    Occurs check: cannot construct the infinite type: a0 = [a0]
        Expected type: [[a0]]
          Actual type: [a0]
        In the first argument of `head', namely `x'
        In the expression: head x
        In an equation for `myPenultimo':
            myPenultimo (x)
              | (length x) == 1 = x
              | (length x) == 2 = head x
              | otherwise  = myPenultimo (tail x)
    Failed, modules loaded: none.
    
    Perche'?
    Modificare inoltre la funzione in modo che restituisca il penultimo elemento di una lista (definendo penultimo di [] come [] e penultimo di una lista con un solo elemento come l'unico l'elemento).

  • Soluzione









    ESERCIZI PROGRAMMAZIONE HASKELL






    Esercizio 1

    Scrivere la funzione Haskell "pippo" che corrisponde al lambda termine
                  \xy.yx
    
    Come si puo' fare in modo che, senza modificare la definizione della funzione pippo, questa possa accettare solo elementi numerici come primo input?
  • Possibile soluzione.

    Esercizio 2

    Definire una funzione Haskell ricorsiva che prenda in input un numero naturale n e calcoli la somma di tutti i numeri pari da 0 a n. (Usare il predicato Haskell che controlla se un numero e' pari  )

    Esercizio 3

    Definire in Haskell la funzione "manoh" che, preso un numero n, restituisce la somma dei quadrati dei naturali da 0 ad n.
    Esercizio 4

    Definire in Haskell la funzione "mavah" che, preso un numero n, restituisce il quadrato della somma dei naturali da 0 ad n.
    Esercizio 5

    Definire in Haskell la funzione "madaih" che, preso un numero n, restituisce la somma dei naturali da 0 ad n.
    Esercizio 6

    Definire in Haskell la funzione "masih" che, preso un numero n, restituisce il quadrato della somma dei naturali da 0 ad n.
    Esercizio 6.5
    Supponiamo di aver definito in Scheme una funzione a valori booleani (un predicato) "cucu". Definire una funzione Scheme che, dati in input due numeri naturali n ed m (n ≤ m), restituisca la somma di tutti i numeri compresi tra n ed m che soddisfano il predicato "cucu".
    Esercizio 7
    Fornire una funzione Haskell che, preso in input un predicato p sui naturali restituisca una funzione sui naturali che vale 2 sui numeri su cui p e' vero e 3 sui numeri su cui p e' falso.

    Esercizio 8


    Esercizio 8.1


    Esercizio 9


    Esercizio 10


    Esercizio 11
    Definire la funzione Haskell che implementi l'insertion sort su liste, avendo come parametro anche la relazione di precedenza.
  • Possibile soluzione.

    Esercizio 12 (un po' complesso)
    Definire la funzione Haskell che, dato un grafo e due nodi, restituisca l'insieme dei cammini (privi di cicli) dal primo al secondo nodo.
  • Possibile soluzione.

    Esercizio 13
  • Definire in Haskell i tipi di dato Abn ("Albero binario con etichette numeriche") e Abf ("Albero binario con etichette di tipo Int -> Int"). Definire due semplici elementi di tipo Abn e Abf.
  • Definire una funzione Haskell
    appT :: Abf -> Abn -> Abn
    
    
    che prenda un albero Abf ed uno Abn con la stessa struttura (non occorre implementare il controllo che abbiano la stessa struttura) e restituisca un albero Abn (con la stessa struttura degli alberi in input) in cui le etichette corrispondano alle applicazioni delle funzioni dell'albero Abf ai numeri dell'albero Abn.
  • Nel caso di alberi con struttura differente, e volendo gestire tale situazione non con la generazione di un messaggio di errore, si potrebbe utilizzare la monade Maybe. Ridefinire quindi la funzione appT in modo che abbia il seguente tipo
    appT :: Abf -> Abn -> (Maybe Abn)
    

  • Possibile soluzione.

    Esercizio 14

    Esercizio 15 Definire in Haskell la lista di tutti i numeri naturali a partire da 1.
    Utilizzarla per definire la funzione che, preso un predicato sui numeri, restituisca la lista di tutti i numeri che soddisfano il predicato.
  • Possibile soluzione.

    Esercizio 16 Utilizzare l'esercizio 15 per definire la lista di tutti i multipli comuni a due numeri e da questa la funzione che calcoli il minimo comune multiplo.
  • Possibile soluzione.

    Esercizio 17 Definire il tipo di dato parametrico degli alberi etichettati in cui ogni nodo puo' avere un numero arbitrario di figli.
    Definire quindi la funzione innesta che, presa in input un'etichetta label e due alberi, inserisca il secondo albero come primo figlio di tutti i nodi del primo albero che hanno label come etichetta.
    Rendere il tipo di dato membro della classe Eq, in modo che sugli alberi la funzione di uguaglianza corrisponda all'uguaglianza della loro struttura, senza considerare le etichette.
  • Possibile soluzione.

    Esercizio 18 La seguente funzione Scheme prende in input un predicato su numeri una lista ls contenente numeri o liste di numeri a qualsiasi livello di annidamento e restituisce una lista uguale ad ls, ma con 0 al posto dei numeri che soddisfano il predicato p?
    define (guess p? ls)
      (if (null? ls)
          '()
          (cons (cond
                  ( (not (number? (car ls)))   (guess p? (car ls)) )
                  ( (p? (car ls)) 0 )
                  (  else (car ls) ) )
                (guess p? (cdr ls)) ) ) )
    
    Scrivere una funzione Haskell che faccia la stessa cosa.
  • Possibile soluzione.

    Esercizio 19 Definire in Haskell la lista di tutti i numeri naturali a partire da 1.
    Utilizzarla per definire la funzione che, preso un predicato sui numeri, restituisca la lista di tutti i numeri che soddisfano tale predicato.

    Esercizio 20 La sonda Spirit ha trovato che su Marte esistono i Loffioni.
    Un Loffione puo' essere generato da un Gangarone oppure da un Sarrapone, oppure da una sequenza finita di Purpuroni. Un Purpurone viene generato dall'incontro di un Gangarone e un Sarrapone. Su Marte ci sono infiniti sarraponi, ma solo due Gangaroni, il GangaroneA e il GangaroneB.
    Definire in Haskell il tipo di dato astratto Loffione che possa permettere di scrivere programmi Haskell che simulino esperimenti virtuali sui Loffioni.
    Scrivere il programma Haskell che, preso un Loffione, restituisca quante volte il GangaroneA e' intervenuto nella generazione del Loffione dato.
  • Possibile soluzione.

    Esercizio 21
    Programmare la funzione quicksort in Haskell e Erlang, senza ricorsione di coda.
  • Possibile soluzione.

    Esercizio 22

    Esercizio 23 Supponiamo di aver bisogno, dati due tipi A e B, di lavorare con liste contenenti elementi di A e B alternati.
    Definire in Haskell tale tipo di dato. Utilizzarlo poi per definire una funzione "divide" che, presa una lista ls di Int e Bool alternati, restituisca la coppia formata dalle due liste ottenute considerando solo gli elementi Int e quelli Bool in ls.
    Il tipo coppia e' denotato in Haskell con (T1,T2). Il costruttore di coppie e', similmente, (e1,e2). "fst" e' la funzione che restituisce il primo elemento di una coppia, "snd" il secondo.
  • Possibile soluzione.

    Esercizio 24 Discutere brevemente della Tail Recursion.
    Il seguente codice Haskell implementa l'insertion-sort parametrizzato sul un predicato di precedenza, prec.
    insert el [] prec = [el]
    insert el (x:xs) prec = if (prec el x) 
                             then (el:(x:xs))
                             else (x:(insert el xs prec))
    
    
    insertionsort [] prec = []
    insertionsort (x:xs) prec = (insert x (insertionsort xs prec) prec)
    
    Fornire una versione tail-recursive dell'insertion-sort.
    (se servissero, si puo' supporre di avere a disposizione le versioni tail-recursive dell'append e del reverse: appendIt e reverseIt).
  • Possibile soluzione.

    Esercizio 25 Scrivere un programma Haskell che produca la lista di tutti i possibili cammini tra due nodi forniti in input in un grafo non orientato (anch'esso fornito in input).
    Il grafo e' rappresentato da una lista di archi, rappresentati a loro volta da coppie di nodi. I nodi sono rappresentati da numeri interi. Si supponga che se un arco e' rappresentato dalla coppia (n,m), allora il grafo non contiene anche la coppia (m,n). archi
  • Possibile soluzione.

    Esercizio 25.1 Modificare il programma dell'esercizio 25 definendo il tipo grafo come
     
    type Graph = (Set Node, (Node -> (Set Node)))
    



    Esercizio 26 Si fornisca una soluzione dell'esercizio 25 in modo che la chiamata ricorsiva del programma abbia sempre lo stesso grafo come argomento.
  • Possibile soluzione.

    Esercizio 27

    Esercizio 28 Fornire una soluzione che usi ricorsione di coda per l'esercizio 25.
  • Possibile soluzione.

    Esercizio 29 Definire in Haskell il tipo di dato astratto Albero Binario con rami infiniti e con nodi con etichette di tipo parametrico a.
    Costruire poi l'albero infinito con etichette numeriche della forma:
                            
                              1
                             / \
                            /   \
                           /     \
                         2         3
                       /  \       /  \
                     4      5     6   7
                    / \    / \   / .......
                   8   9  10 11 12 ........
                   .......................
    

  • Possibile soluzione.

    Esercizio 30 Sia    data InfNBT = Join Int InfNBT InfNBT
    il tipo di dato degli alberi binari con rami infiniti ed etichette numeriche.
    Si definisca myIT come il seguente elemento di InfNBT
                            
                              1
                             / \
                            /   \
                           /     \
                         2         3
                       /  \       /  \
                     4      5     6   7
                    / \    / \   / .......
                   8   9  10 11 12 ........
                   .......................
    
    e poi si definisca la funzione levelOrder :: InfNBT → [Int] che restituisce la lista delle etichette di un albero infinito ordinate livello per livello da sinistra a destra.
    Per esempio, la valutazione di (levelOrder myIT) produrra' la lista infinita di tutti gli interi a partire da 1.
    (Una possibile soluzione potrebbe utilizzare una funzione che, preso un albero ed un numero n, restituisca la lista di tutti i sottoalberi di livello n)
    Si scriva inoltre la piu' breve espressione Haskell il cui valore e' la lista di tutti gli interi a partire da 1.
  • Possibile soluzione.

    Esercizio 31

    Esercizio 32 Scrivere un programma Haskell che riconosca o rifiuti stringhe appartenenti al linguaggio regolare, sull'alfabeto {a,b,c}, associato alla seguente espressione regolare
    abc*b + aa
    Ricordiamo che il tipo String in Hakell coincide con [Char] e che un carattere si rappresenta tra apici (es.: 'a').
  • Possibile soluzione.

    Esercizio 33 La seguente funzione Erlang firstList2secondList prende due liste non vuote di uguale lunghezza e restituisce una funzione che, preso un elemento della prima lista restituisce l'elemento della seconda lista nella stessa posizione.
    In Erlang la funzione predefinita lists:nth(N,L) restituisce l'N-esimo elemento della lista L. Inoltre la funzione position prende un elemento ed una lista che lo contiene e restituisce la sua posizione. Notare inoltre l'uso di "fun" per denotare una funzione anonima.
    firstList2secondlist(First,Second) -> 
                  fun(Elem) -> N = position(Elem,First);
    	                   lists:nth(N,Second)
    	      end.
    
    Scrivere la stessa funzione in Haskell, senza utilizzare funzioni ausiliarie come position e lists:nth.
    Fornire il tipo principale calcolato da Haskell per la funzione definita.
    Come mai in Haskell e' possibile fornire la funzione richiesta in modo semplice ed elegante, mentre in Erlang cio' risulterebbe piu' complesso?
  • Possibile soluzione.

    Esercizio 34 Si consideri il seguente codice Haskell incompleto
    data ......
    
    treeapply f (Leaf x) = x
    
    treeapply  f (Node n t1 t2) = f n (treeapply f t1) (treeapply f t2)
    
    e si completi con la definizione del tipo di dato in modo che questa risulti la piu' generale possibile.
    Cosa calcola la funzione treeapply?
    Cosa restituisce l'interprete se chiediamo la cosa seguente?
    :type treeapply   
    
    Giustificare la risposta.
  • Possibile soluzione.

    Esercizio 35

    Esercizio 36

    Esercizio XX
  • Possibile soluzione.