programmazione funzionale: ml
DESCRIPTION
implementazione del l -calcolo tipato definizione di nuovi tipi ricorsivi i valori dei nuovi tipi sono termini, che possono essere visitati con un meccanismo di pattern matching (versione semplificata dell’unificazione) scoping statico (a differenza di LISP) - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/1.jpg)
1
Programmazione Funzionale: ML
1
implementazione del -calcolo tipato definizione di nuovi tipi ricorsivi i valori dei nuovi tipi sono termini, che possono essere visitati con
un meccanismo di pattern matching (versione semplificata dell’unificazione)
scoping statico (a differenza di LISP) semantica statica molto potente (inferenza e controllo dei tipi)
• un programma “corretto” per la semantica statica quasi sempre va bene
gestione della memoria a heap con garbage collector
![Page 2: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/2.jpg)
2
Lo strumento utilizzato seconda parte del corso Ocaml (Objective CaML), una estensione, orientata ad
oggetti (e con un frammento imperativo), di uno dei più importanti linguaggi funzionali (ML)
progettato ed implementato all’INRIA (Francia) l’implementazione (per tutte le piattaforme importanti) si
può scaricare dal sitohttp://caml.inria.fr/
il manuale on line al sitohttp://caml.inria.fr/ocaml/htmlman/index.html
![Page 3: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/3.jpg)
3
OCAMLnucleo funzionale puro
funzioni (ricorsive) tipi e pattern matching primitive utili: liste
componente imperativo variabili e assegnamento primitive utili: arrays
moduli e oggettimeccanismi per la definizione di tipi e di tipi di
dato astratto
![Page 4: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/4.jpg)
Applicazione: macchina astratta semantica operazionale: implementazione e
strutture a tempo di esecuzuioone riprenderemo l’interprete di un semplice
linguaggio imperativo (frammento C) visto a Programmazione I
vedremo come utilizzare le caratteristiche del linguaggio ad oggetti (meccanismi di astrazione sui dati)
![Page 5: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/5.jpg)
Seguendo il tutorial sessione interattiva l’utente scrive frasi CAML che iniziano con
prompt #a seguito del prompt, il sistema compila le frasi,
le esegue e stampa il risultato della valutazione per ogni frase il risultato e’ un valore ed il tipo
(type inference)
![Page 6: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/6.jpg)
6
Espressioni pure Objective Caml version 2.00+3/Mac1.0a1
# 25;;
- : int = 25
# true;;
- : bool = true
# 23 * 17;;
- : int = 391
# true & false;;
- : bool = false
# 23 * true;;
This expression has type bool but is here used with type int
# if 2 = 3 then 23 * 17 else 15;;
- : int = 15
# if 2 = 3 then 23 else true;;
This expression has type bool but is here used with type int
![Page 7: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/7.jpg)
7
Funzioni# function x -> x + 1;;
- : int -> int = <fun>
# (function x -> x + 1) 3;;
- : int = 4
# (function x -> x + 1) true;;
This expression has type bool but is here used with type int
anche i parametri delle funzioni non richiedono
annotazioni di tipo (il tipo e’ inferito dal loro uso nel
corpo)il valore di una funzione e’ <fun>
![Page 8: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/8.jpg)
8
Funzioni# function x -> x;;
- : 'a -> 'a = <fun>
# function x -> function y -> x y;;
- : ('a -> 'b) -> 'a -> 'b = <fun>
# (function x -> x) 2;;
- : int = 2
# (function x -> x) (function x -> x + 1);;
- : int -> int = <fun>
# function (x, y) -> x + y;;
- : int * int -> int = <fun>
# (function (x, y) -> x + y) (2, 33);;
- : int = 35
‘a e’ una variabile di tipo, puo’ assumere qualsiasi tipo (polimorfismo)le funzioni sono valori, possono essere passate come parametri
(funzioni di ordine superiore)
![Page 9: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/9.jpg)
Il costrutto let \ let in permette di definire un nuovo identificatore a con
associato un valore valori: simple expressions o funzioni
![Page 10: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/10.jpg)
10
Let binding# let x = 3;;
val x : int = 3
# x;;
- : int = 3
# let y = 5 in x + y;;
- : int = 8
# y;;
Unbound value y
• (definizione globale/locale)
![Page 11: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/11.jpg)
11
Let binding# let f = function x -> x + 1;;
val f : int -> int = <fun>
# f 3;;
- : int = 4
# let f x = x + 1;;
val f : int -> int = <fun>
# f 3;;
- : int = 4
# let fact x = if x = 0 then 1 else x * fact(x - 1) ;;
Unbound value fact
![Page 12: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/12.jpg)
12
Let rec binding# let rec fact x = if x = 0 then 1 else x * fact(x - 1)
;;
val fact : int -> int = <fun>
# fact (x + 1);;
- : int = 24
![Page 13: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/13.jpg)
Typeper definire nuove strutture dati vengono
forniti records e variants (unione)entrambi si definiscono con una
dichiarazione di tipo type
![Page 14: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/14.jpg)
14
Record# type ratio={num:int; denum:int};;
type ratio={num:int; denum:int}
# let x={num=1;denum=3);;
val x: ratio={num=1;denum=3;}
# x.num;;
- int =1
• un record per memorizzare numeri razionali
• creare e selezionare i campi
![Page 15: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/15.jpg)
15
Unione disgiunta, variant• enumera tutti i casi che possono assumere i
valori di quel tipo
• ogni caso e’ identificato da un nome (costruttore) che serve per costruire valori di quel tipo e per riconscerlo per pattern-matching
• utile per definire tipi di dato ricorsivi
![Page 16: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/16.jpg)
# type number = | Int of int | Float of float | Error;;
type number=
| Int of int
| Float of float
| Error
# let add_num n1 n2=
match (n1,n2) with
(Int i1,Int i2)--->.......
(Int i1,Float i2)--->
(Float i1,Float i2)--->
(Float i1,Int i2)--->
(Error,-)---------->Error
(-,Error)---------->Error
val add_num: number->number->number=<fun>
# Int 3;;
- : number= Int 3;
![Page 17: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/17.jpg)
17
Espressioni: sintassi astratta# type ide = string;;
type ide = string
# type expr = | Den of ide | Val of ide | Fun of ide * expr
| Plus of expr * expr | Apply of expr * expr;;
type expr =
| Den of ide
| Val of ide
| Fun of ide * expr
| Plus of expr * expr
| Apply of expr * expr
E ::= I | val(I) | lambda(I, E1) | plus(E1, E2) | apply(E1, E2)
# Apply(Fun("x",Plus(Den "x", Den "x")), Val "y");;
- : expr = Apply (Fun ("x", Plus (Den "x", Den "x")), Val "y")
![Page 18: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/18.jpg)
18
L’ambiente# type eval = Int of int | Bool of bool | Efun of expr
| Unbound;;
type eval = | Int of int | Bool of bool | Efun of expr | Unbound
# type env = ide -> eval;;
type env = ide -> eval
# let bind (rho, i, d) =
function x -> if x = i then d else rho x;;
val bind : (ide -> eval) * ide * eval -> (ide -> eval) = <fun>
- env = IDE eval
- eval = [ int + bool + fun ]
![Page 19: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/19.jpg)
19
Comandi: sintassi astratta# type com = Assign of ide * expr | Ifthenelse of expr *
com list * com list | While of expr * com list;;
type com =
| Assign of ide * expr
| Ifthenelse of expr * com list * com list
| While of expr * com list
C ::= ifthenelse(E, C1, C2) | while(E, C1) | assign(I, E) | cseq(C1, C2)
# While(Den "x", [Assign("y", Plus(Val "y", Val "x"))]);;- : com =
While (Den "x", [Assign ("y", Plus (Val "y", Val "x"))])
![Page 20: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/20.jpg)
20
Tipi e pattern matchingtype expr = | Den of ide | Fun of ide * expr | Plus of expr * expr | Apply of expr * exprtype eval = | Int of int | Bool of bool | Efun of expr | Unboundtype env = ide -> eval
E(I, ) = (I) E(plus(E1, E2), )= E(E1, ) + E(E2, )E(lambda(I, E1), )= lambda(I, E1)E(apply(E1, E2), ) = applyfun(E(E1, ),E(E2, ),)applyfun(lambda(I, E1), d,) = E(E1) [ / I d ] # let rec sem (e, rho) = match e with | Den i -> rho i | Plus(e1, e2) -> plus(sem (e1, rho), sem (e2, rho)) | Fun(i, e) -> Efun(Fun(i, e)) | Apply(e1, e2) -> match sem(e1, rho) with | Efun(Fun(i, e)) -> sem(e, bind(rho, i, sem(e2, rho)) | _ -> failwith("wrong application");;val sem : expr * env -> eval = <fun>
![Page 21: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/21.jpg)
Un tipo primitivo utile: le listeSi costruiscono enumerando esplicitamente
gli elementi, racchiusi tra []Oppure a partire dalla lista vuota [] tramite
l’operatore di consOperazioni primitive standard
![Page 22: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/22.jpg)
22
Liste# let l1 = [1; 2; 1];;
val l1 : int list = [1; 2; 1]
# let l2 = 3 :: l1;;
val l2 : int list = [3; 1; 2; 1]
# let l3 = l1 @ l2;;
val l3 : int list = [1; 2; 1; 3; 1; 2; 1]
# List.hd l3;;
- : int = 1
# List.tl l3;;
- : int list = [2; 1; 3; 1; 2; 1]
# List.length l3;;
- : int = 7
![Page 23: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/23.jpg)
Caratteristiche Imperativevariabili e assegnamentoarrays (mutabili)comandi iterativi, while, for
![Page 24: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/24.jpg)
24
Variabili e frammento imperativo
# let x = ref(3);;val x : int ref = {contents=3}# !x;;- : int = 3# x := 25;;- : unit = ()# !x;;- : int = 25# x := !x + 2; !x;;- : int = 27
references sono mutable indirection cells, il cui
valore puo’ essere modificato da un assegnamento
![Page 25: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/25.jpg)
25
Un tipo primitivo mutabile: l’array# let a = [| 1; 2; 3 |];;
val a : int array = [|1; 2; 3|]
# let b = Array.make 12 1;;
val b : int array = [|1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1|]
# Array.length b;;
- : int = 12
# Array.get a 0;;
- : int = 1
# Array.get b 12;;
Uncaught exception: Invalid_argument("Array.get")
# Array.set b 3 131;;
- : unit = ()
# b;;
- : int array = [|1; 1; 1; 131; 1; 1; 1; 1; 1; 1; 1; 1|]
![Page 26: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/26.jpg)
26
Programmi Stand-alone
Il programma da eseguire deve essere memorizzato in un file .ml
Compilare ed eseguire
![Page 27: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/27.jpg)
27
Esercizio 1
Funziona per ordinare una lista polimorfaLe liste sono un tipo di dato primitivo immutabile
(in stile funzionale), a differenza degli arrayLa funzione sort ha tipo 'a list -> 'a list
• Gli operatori di confronto (=,<=,….) sono
polimorfi, si applicano ad ogni tipo
![Page 28: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/28.jpg)
Cosa vogliamo?# let l1 = [6; 2; 5; 3];;val l1 : int list = [6; 2; 5;3]
# sort l1 ;;- : int list = [2; 3; 5;6]
# let l2 = [3.14; 2.17];;val l1 : int list = [3.14; 2.17]
# sort l2 ;;- : float list = [2.17; 3.14]
• La lista passata come input non e’ modificata, la funzione restituisce una nuova lista, che contiene gli elementi in ordine crescente
![Page 29: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/29.jpg)
Insertion sortRealizzare sort in modo ricorsivo caso base: [] caso ricorsivo cons: head:: tail
• Pattern matching • Insertion sort (funzione ausiliaria che
inserisce un elemento in una lista ordinata)
![Page 30: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/30.jpg)
Funzioni di ordine superiorein puro stile funzionale le funzioni sono
valori, possono essere passate come parametri ad altre funzioni
• E’ utile per realizzare operazioni su
strutture dati
![Page 31: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/31.jpg)
List.map# let l1 = [6; 2; 5; 3];;val l1 : int list = [6; 2; 5;3]
# List.map (function n -> n+1) l1 ;;- : int list = [7; 3; 6;4]
• E’ un funzionale standard, applica una funzione ad ogni elemento di una lista
• E’ fornito dalla libreria, ma non c’e’ niente di magico• Definiamolo, come una funzione ricorsiva di ordine
superiore
![Page 32: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/32.jpg)
32
Alberi binari
Definire un tipo unione ‘a btree che specifica alberi binari polimorfi
Definizione ricorsiva:
caso base: vuoto
caso ricorsivo: un nodo che contiene un valore
di tipo ‘a, e due sottoalberi ‘a btree sx e dx
![Page 33: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/33.jpg)
Btree# type ‘a btree= Empty| Node of ‘a * ‘a btree * ‘a btree;;type ‘a btree= Empty| Node of ‘a * ‘a btree * ‘a btree
# Empty;;- : ‘a btree = Empty
# Node(1,Empty,Empty);;-: int btree = Node(1,Empty,Empty)
# Node;;the constructor node expects 3 arguments, but is here applied to zero
arguments
![Page 34: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/34.jpg)
FunzioniScrivere una funzione che, dato un ‘a btree,
calcola il numero di nodi Ordered Binary Btree: ‘a btree polimorfi ma
ordinati, il sottoalbero sx ha un valore strettamente minore, e quello dx un valore strettamente maggiore di quello del nodo
Scrivere due funzioni che, dato un ordered ‘a btree ed un valore x di tipo ‘a , fanno la ricerca o l’inserimento di x
![Page 35: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/35.jpg)
OsservazioneLe funzioni member e insert come
parametro un btree Assumiamo che sia di tipo OrderedNon possiamo definire un tipo di dato
Ordered per costruzioneChe cosa serve? Un meccanismo per
definire un tipo di dato astratto
![Page 36: Programmazione Funzionale: ML](https://reader035.vdocuments.net/reader035/viewer/2022062217/568151a6550346895dbfd584/html5/thumbnails/36.jpg)
Tipi di dato astrattoDati + operazioni : insiemeIn questo modo possiamo definire proprieta’
dei dati (tipo l’ordine per costruzione)Meccanismi di astrazione, incapsulamento
dell’informazione, in modo da garantire che le proprieta’ non siano violate dal codice che usa il tipo di dato