![]()
Lenguaje Haskell. Estructuras complejas
![]()
1 Tipos de estructuras de datos
2 Construcción y acceso de estructuras de datos
3 Estructura de datos LISTA. Definición y Operaciones. Listas Infinitas
![]()
En Haskell vamos a diferenciar dos tipos de estructuras complejas: tuplas y listas.
Las tuplas son conjuntos o secuencias heterogéneas de elementos, con una longitud (nº de elementos), predefinida que no puede variar.
Las listas son secuencias de elementos del mismo tipo, cuya longitud puede variar e incluso, no especificarse: listas infinitas.
Construcción y acceso de estructuras de datos
Para construir una tupla utilizamos la sintaxis siguiente:
(t1, t2, ... , tn)
La tupla posee n elementos. Por tanto, si escribimos una función que acepte como parámetro esta tupla, necesariamente la tupla actual que sirva de argumento a una llamada a la función debe contar con n elementos exactamente. La signatura de la tupla es:
(tipo1, tipo2, ... , tipon)
Por ejemplo, si definimos la suma entre pares de elementos el código de la función quedaría del modo que sigue:
suma::(Int, Int)->Int
suma (x, y)=x+y
Esta función es completamente distinta de aquella que suma dos números:
suma::Int->Int->Int
suma x y=x+y
La primera acepta una tupla de dos elementos enteros mientras que la segunda acepta dos números enteros independientes no agrupados en estructura compleja alguna.
Otra estructura compleja muy utilizada es la LISTA, que vamos a describir detalladamente en la sección siguiente.
Estructura de datos LISTA. Definición y Operaciones. Listas Infinitas
Como ya hemos comentado, una lista se puede definir como una secuencia de elementos del mismo tipo. Por ejemplo [1,2,-3,0] constituye una lista de elementos enteros. Una función que acepta como parámetro una lista, puede trabajar con un argumento actual de cualquier longitud, siempre que los elementos sean del tipo especificado en la signatura, en el caso de que aparezca, y la lista sea homogénea.
Las listas se pueden representar de formas diversas, como ocurría en Prolog:
Para realizar operaciones con listas en Haskell debemos acoger el método que usábamos en Prolog: recursividad. Recordemos que recursividad y backtraking no son lo mismo, así pues, en Haskell no aparece la idea de backtracking en la ejecución de los programas.
La sintaxis para especificar los datos de una lista es variada:
Haskell proporciona un conjunto de funciones predefinidas para el manejo de listas:
También proporciona una sintaxis de contrucción de listas muy potente: Listas de Números y List Comprehension.
Listas de Números
Como en otros lenguajes funcionales podemos utilizar una notación especial para las listas de números donde la diferencia entre elementos consecutivos es constante
Para las listas donde la diferencia no es 1, la notación es [m,k..n], siendo m el primer elemento de la lista, k el segundo, los siguientes se diferencian entre ellos lo mismo que m y k y ningún elemento de la lista puede ser mayor que n. Por ejemplo [2,4..10] es lo mismo que [2,4,6,8,10].
List Comprehension
La notación List Comprehension es similar a la utilizada en matemáticas para construir conjuntos, y puede ser muy útil a la hora de construir ciertos tipos de listas. La sintaxis es como sigue:
[expresion|calificador,calificador,...]
Con esta expresión se genera una lista donde los elementos son de la forma de expresion y cumplen las condiciones expresadas en los calificadores.
La expresión puede ser cualquier expresión válida y los calificadores pueden ser de 3 tipos: generadores, filtros y definiciones locales.
Veamos algunos ejemplos de construcción de listas:
[n|n<-[1..5]]
Þ [1,2,3,4,5][n*n|n<-[1..5]]
Þ [1,4,9,16,25][n|n<-[1..5], par n]
Þ [2,4][(n, n*n)|n<-[1..3], n<n*n]
Þ [(2,4),(3,9)][n*n|n=2]
Þ [4][1|n<-[1..5]]
Þ [1,1,1,1,1][(i,j)|i<-[1..2], j<-[1..2]]
Þ [(1,1), (1,2), (2,1), (2,2)]Ejemplos
Para entender adecuadamente lo expuesto en los puntos anteriores, veamos algunos ejemplos interesantes de manejo de listas.
|
|
Ejemplos |
|
Ejemplos que ilustran la utilización de listas. Función que me dice si un número es o no primo. divisores Int->[Int] divisores n=[d|d<-[1..n], n ‘mod’ d==0] primo Int->Bool primo n=(divisores n==[1,n]) Función que devuelve el nésimo elemento de una lista. enesimo Int->[Int]->Int enesimo 1 (c:cola)=c enesimo n (c:cola)=enesimo(n-1) cola Función que invierte una lista. invertir [Int]->[Int] invertir []=[] invertir (c:cola)=invertir cola++[c] |
|