4 nov 2007

listas por comprensión

Si quisiera tener una lista de los primeros 500 numeros naturales sería muy tedioso tener que escribir los 500 elmentos de la lista, en Haskell podemos escribir:
listaTediosa = [1..500]

Y ya, en listaTediosa tenemos los numeros naturales, entre 1 y 500

listaInfinita = [34..]


Produciría como resultado la lista de "todos" los enteros mayores a 34

En los ejemplos anteriores los (..) indican que la diferencia entre dos numeros consecutivos (en cuanto a la aparición) en la lista es de uno

Si queremos tener en nuestra lista numeros enteros, tal que dos elementos consecutivos en ella,su diferencia no sea de uno, sino de 5.

distaCinco = [3,8..]

Produciria [3,8,13,18,23,28,33,38,43,48,53,58,63,68,73,78,83,88,93,98,....., que es lo que queriamos


Todo esto gracias a la evaluación perezosa, virtud de Haskell, que nos permite hacer uso de listas infinitas.

Listas por compresión

En matemáticas las definiciones de conjuntos es muy común, por ejemplo si queremos denotar al conjunto de los numeros que son mayores que 3456 y menores a 45678 escribimos:



Al conjunto de los numeros impares





En Haskell podemos definir esos conjuntos de la siguiente manera:

Y = [x|x <-[2456..45678]] I= [2*x+1 |x <-[1..]] Son muy similares las definiciones, otros ejemplos de listas por comprension son -- Verfica que a es elemento de xs checa a xs = or [ a==b | b <- xs] -- Aplana lista de listas aplana xs = [ a | x <- xs, a <- x] -- map con listas por comprensión map f xs = [f x | x <- xs] --ternas pitagoricas ternaspit n = [ (x,y,z) | let ns = [1..n], x <- ns, y <- ns, z <- ns, x^2 + y^2 = z^2] Las listas por comprension nos pueden ayudar a definir una cantidad de conjuntos y de funciones muy grande, la notación que se usa al ser muy parecida a la usada en matemáticas da cierta elegancia y facilidad de "comprender" lo que se quiere o ha definido Un ejemplo bonito

El siguiente ejemplo es muy usado para "presumir" el paradigma funcional, y destacar sus virtudes frente a los lenguajes imperativos, se trata del algoritmo quicksort para listas de numeros.

qsort [] = []
qsort (x:xs) = qsort [ y | y <- xs, y <= x]++ [x] ++ qsort [ y | y <- xs, y > x]

si, son solo DOS líneas de código, se ve chido ¿no? , en un lenguaje imperativo nos llevariamos fácil mas de 10 líneas de código, además de que la definición de este algoritmo en Haskell es transparente, es decir que a primera vista vemos que se trata de quicksort,mientras que en un lenguaje imperativo tardariamos poco/mucho mas en enteder que es lo que hace el algoritmo.



No hay comentarios:

ga