1 / 19

Llistes

Llistes. L’estructura de dades llista és d’importància cabdal en els llenguatges funcionals. Són preferides als conjunts pels seus avantatges computacionals, a més de permetre la repetició de components. Les llistes són seqüències d’elements del mateix tipus, a diferència de LISP.

jag
Download Presentation

Llistes

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Llistes • L’estructura de dades llista és d’importància cabdal en els llenguatges funcionals. Són preferides als conjunts pels seus avantatges computacionals, a més de permetre la repetició de components. • Les llistes són seqüències d’elements del mateix tipus, a diferència de LISP. • Així, tenim: T és un tipus • ----------------------- • T list és un tipus int list (bool * string) list (bool -> int) list (int list) list ‘a list [1, 3, 56, 45] [(true “a”), (false “b”)] [(fn true => 2 | false =>3)] [[1, 2, 3], [2, 3, 2]] []

  2. Constructors de llistes • La llista buida, anomenada ‘nil’, s’escriu: • [] : ‘a list • és de tipus polimòrfic, és a dir, representa la llista buida de qualsevol tipus. • La construcció de llistes es fa a partir de l’operador ‘cons’, que en SML s’escriu :: • :: : ‘a * ‘a list -> ‘a list’ Nil i cons són anomenats constructors de llistes. Juguen un paper dual, s’utilitzen en la descripció dels valors i són també els noms d’operacions. [3, 2, 4, 3] == 3::[2, 4, 3] == 3::2::[4, 3] == 3::2::4::[3] == 3::2::4::3::[]

  3. Unicitat de la representació • 1) els valors de tipus T list es generen pels constructors [] i :: sobre valors de tipus T. • 2) les llistes són construides de forma única per :: i []. Això vol dir que [] no és igual a cap llista construida a partir de ::, i que a::x ==b::y si i nomes si a ==b i x ==y. • Els detalls d’implementació de llistes són amagats als programadors. No sabem quina seqüència de posicions de memòria conté la llista. • Així, canviar un component d’una llista no significa destruir els continguts d’una posició de memòria, sinò obtenir una nova llista a partir de l’anterior.

  4. Operacions sobre llistes • @ : ‘a list * ‘a list -> ‘a list (infix) • rev: ‘a list -> ‘a list • explode: string -> string list • implode: string list -> string • link: (‘a list) list -> ‘a list • length: ‘a list -> int • hd: ‘a list -> ‘a • tl: ‘a list -> ‘a list • null: ‘a list -> bool • upto: int * int -> int list (infix) • sumlist: int list -> int • prodlist: int list -> int • doublelist: int list -> int list • copy: int -> ‘a -> ‘a list member: ‘‘a list ->‘‘a= -> bool map: (‘a -> ‘b) -> ‘a list -> ‘b list

  5. Seccions • Algunes vegades necessitarem versions currificades dels constructors de llistes. Així definim • fun cons a x = a :: x • fun consonto x a = a :: x • fun append x y = x @ y • Hi ha una notació, anomenada secció, no permesa en SML, que no obligaria a definir les funcions anteriors: • cons a == (a::); consonto x == (::x) • Vegeu també una funció d’intercanvi C interessant • fun C f x y = f y x • així tindriem les equivalències: • val consonto = C cons • val rappend = C append

  6. Combinacions • Amb les funcions introduides fins ara es poden definir una infinitat de noves funcions com a combinació d’elles • consr 3 [1, 2, 5] == [1, 2, 5, 3] • fun consr a x = rev(a::rev x) • fun consr a x = x @ [a] • palindrom [1, 2, 3] == [1, 2, 3, 3, 2, 1] • fun palindrom x = x@(rev x) • drop 2 [1, 2, 3, 4, 5] == [3, 4, 5] • fun drop n = repeat n tl • Una forma habitual de definir funcions sobre llistes és distingir dos casos, la llista buida i les construides a partir de l’operador ::. Aquesta és la forma habitual en LISP. • En SML hi ha una forma alternativa, l’acarament de patrons.

  7. Acarament de patrons en llistes fun sumlist []=0 | sumlist (a::x) = a + sumlist x • Com les llistes són de la forma [] o bé a::x permetrem l’aparició de [] i :: en els patrons de definició de funcions. • En cada cas el paràmetre de la definició és un patró construït a partir de constructors i variables. Per exemple, compareu: fun sumlist x = if null x then 0 else hd x + sumlist (tl x) amb: Considereu l’equivalència de [a, b] amb a::b::[]

  8. Definició de patró • Un patró és: • 1) una variable, o • 2) una constant, o • 3) un constructor aplicat a un patró. • amb la restricció que una variable només pot aparéixer una vegada en un patró. Els llenguatges funcionals funcionen per acarament de patrons i no per unificació. fun alternar (a::b::x) = b::alternar x | alternar [a] = [] | alternar [] = [] fun member (a::x) b=if a = b then true else member x b | member [] b = false

  9. Funcions d’ordre superior • La forma habitual de manipulació de llistes és la recursió. Ara bé, és útil disposar de funcions (d’ordre superior) que facilitin aquesta manipulació per incrementar la llegibilitat del codi. fun map f (a::x) = (f a)::map f x | map f [] = [] map lengths [“una”,“llista”,“de”,“cadenes”] == [3,6,2,7] map g (map f x) == map (g o f) x == ((map g) o (map f)) x fun filter pred (a::x) = if pred a then a::filter pred xelse filter pred x | filter pred [] = []

  10. Més funcions d’ordre superior • fun exists pred (a::x) = if pred a then true • else exists pred x • | exists pred [] = false • fun all pred (a::x) = if pred a then all pred x else false • | all pred [] = true • fun zip f [] [] = [] • | zip f (a::x) (b::y) = f a b :: zip f x y • | zip f x y = error “llistes de long. diferent” • val sumallistes = zip plus • val prodllistes = zip times • val parellllistes = zip pair

  11. Acumular fun accumulate f a (b::x) = accumulate f (f a b) x | accumulate f a [] = a • Una altra funció habitual sobre llistes és iterar l’aplicació d’una funció i accumular el resultat en un sol valor. Vegeu la seva utilització: val sumlist= accumulate plus 0 val prodlist = accumulate times 1 val link = accumulate append [] val implode = accumulate concat ““ fun max a b = if a < b then b else a fun maxlist (a::x) = accumulate max a x | maxlist [] = error “maxim d’una llista buida”

  12. Reduir • De vegades interessa associar arguments per a una funció binària per la dreta en comptes de per l’esquerra com en el cas anterior • f a1 (f a2 (... (f an a) ...)) en comptes de • f (...(f (f a a1) a2) ...) an fun reduce f a (al::rest) = f al (reduce f a rest) | reduce f a [] = a Aquestes dues funcions són duals, una es pot definir en funció de l’altre fent el reverse de la llista argument. Si la funció f és conmutativa, la funció accumulate i reduce són equivalents. Així, per exemple sumlist es pot definir de les dues maneres perque plus és conmutativa.

  13. Ordenació de llistes • Veurem dos algorismes. el primer, i més senzill, consisteix en col.locar un element en una llista respectant l’ordre imposat per una funció (currificada) d’ordre. fun insertwrt before item [] = [item] | insertwrt before item (a::x) = if before a item then item::a::x else a::insertwrt before item x Noteu que la funció before ha de definir un ordre total, i per tant ha de ser transitiva, antisimètrica i o bé before a b = true o bé before b a = true. fun insert_sortwrt before = letfun insertin x a = insertwrt before a x in accumulate insertin [] end

  14. Quicksort • Ara veurem un algorisme eficient d’ordenació de llistes, Primer una versió per ordenació de llistes d’enters i després una versió paramètrica. fun sort [] = [] | sort (a::x) = letval low = filter (lessthan a) x and high = filter (non (lessthan a)) x in sort low @ [a] @ sort high fun sortwrt before = letfun sort [] = [] | sort (a::x) = letval low = filter (before a) x and high = filter (non (before a)) x in sort low @ [a] @ sort high in sort end

  15. Inducció i llistes • De vegades necessitarem verificar que certes propietats es verifiquen per a totes les llistes. Per exemple, • f x == g x per a tot x: ‘a list • La manera de fer-ho és via inducció estructural. La inducció estructural fa ús de l’estructura recursiva de les dades, en aquest cas llistes, per definir el pas d’inducció. • Principi d’inducció estructural per llistes: • Per tal de provar que P(x) es verifica per totes les llistes (finites i ben definides) x:T list • només cal provar: • (1) P([]) és cert • (2) P(a::y) se segueix d’assumir P(y) per a tot y :Tlist ben definida i finita, i per a tot element a:T ben definit.

  16. Exemple d’inducció structural • Provarem que per a tota x: ‘a list • map f (map g x) = map (f o g) x • (1) (Cas base) map f (map g [])) = map f [] = [] = • = map (f o g) [] • (2) (Pas d’inducció) Per a qualsevol a : ‘a i y : ‘a list • If map f (map g y) = map (f o g) y (HI) llavors • map f (map g (a::y)) = map (f o g) (a::y) • map f (map g (a::y)) = map f (g a :: map g y) (Definició) • = f (g a) :: map f (map g y) • = f (g a) :: map (f o g) y (HI) • = (f o g) a :: map (f o g) y (definició de o) • = map (f o g) (a::y) (definició de map)

  17. Generalització d’objectius • De vegades les proves per inducció fracassen per que la hipòtesi d’inducció és massa feble. La solució consisteix en generalitzar l’objectiu; fent-lo més fort. Veurem un exemple. Suposant les definicions: fun [] @ y = y | (a::x) @ y = a::(x @ y) fun revonto x [] = x | revonto x (a::y) = revonto (a::x) y fun rev x = revonto [] x Volem provar que per a tota x, y: ‘a list es verifica revonto y (rev x) = x @ y (OBJ)

  18. Fracàs en la prova • Un intent directe de fer la prova ens conduirà a la necessitat de provar (en el pas d’inducció): • revonto y (revonto [a] x) = a :: (x @ y) • utilitzant l’expressió (derivada de la HI): • revonto y (revonto [] x) = x @ y • En aquest punt estem bloquejats. El problema és que necessitem generalitzar revonto [] x a la hipòtesi d’inducció en revonto r x per a qualsevol r:’a list. Això vol dir que l’objectiu s’ha de reformular • revonto y (revonto r x) = revonto (x @ y) r (G) • Obviament (G) implica (OBJ) • revonto y (rev x) = revonto y (revonto [] x) • = revonto (x @ y) [] (G amb r = []) • = x @ y

  19. Prova de l’objectiu generalitzat • revonto y (revonto r x) = revonto (x @ y) r (G) • (1) (Cas base) (x = []) • revonto y (revonto r []) = revonto y r (def. revonto) • = revonto ([] @ y) r (def. @) • (2) (Pas d’inducció) (x = a::z) • revonto y (revonto r (a::z)) = • = revonto y (revonto (a::r) z) = • = revonto (z @ y) (a::r) = (per HI) • = revonto (a::(z @ y)) r = (def. revonto) • = revonto ((a::z) @ y) r (def. @) • Trobar la generalització adient en cada cas és la part més imaginativa de les proves per inducció.

More Related