Imaginemos un mundo libre

La paz interior comienza en el momento en el que decides no permitir, que ninguna persona o evento, tome el control de tus emociones.

Listas en Haskell

with 19 comments

Una lista es una estructura de datos que representa un conjunto de datos de un mismo tipo, es muy usada e importante en el lenguaje haskell.

Su declaración es muy simple, ejem:

[Int]: Representa una lista de enteros [4,5,9,25,60 ]

[Char]: Representa una lista de chars [‘l’,’i’,’n’,’u’,’x’]

[Bool]: Representa una lista de valores booleanos [True, False, True]

[String]: Representa una lista de strings [“buenas”,”noches”]

[Float]: Representa una lista de flotantes [2.5,5.8,4.3,7.1 ]

También podríamos definir una lista de listas así: [[Int]], pero eso lo veremos más adelant con el tema de matrices. Una lista vacía se representa [] y algo importante para el manejo de listas es separar el primer elemento (cabeza), del resto(cola) de la sgt manera(x:xs) . X representa la cabeza y xs la cola.

Como Haskell hace mucho uso de la recursividad entonces, debemos tener en cuenta cuando deterne la operación recursiva y para ello necesitamos un caso base.

Vamos a ver algunos ejemplos:

1.- Sumar los elementos de una lista.En este caso, el caso base es que la lista se encuentre vacía y devuelve 0, mientras tanto que siga sumando los elementos con la operación recursiva.

sumar::[Int]->Int
sumar [ ] = 0
sumar (x:xs) = x + sumar(xs)

Main> sumar [5,4,7,8]
24
2.- Invertir una lista: El operador Ord me sirve para indicar que representa a cualquier tipo de dato.

invertir::Ord a=>[a]->[a]
invertir [ ] = [ ]
invertir (x:xs) = (invertir xs)++[x]

Main> invertir [5,4,7,8]
[8,7,4,5]

3.- Comparar si 2 listas son iguales:

igualLista:: Eq a => [a]->[a]->Bool
igualLista l1 l2 = l1 == l2

Main> igualLista [“Hola”,”Mundo”] [“Mundo”,”Hola”]
False

4.- Comprobar si una lista esta ordenada: En este caso ‘y’ representa al 2do elemento de la lista.

lista_ordenada::Ord a=>[a]->Bool
lista_ordenada [] = True
lista_ordenada [_] = True
lista_ordenada (x:y:xs) = (x<=y) && lista_ordenada (y:xs)

Main> lista_ordenada [‘a’,’b’,’c’,’d’]
True

5.- Mostrar el elemento que se encuentra en cierta ubicacion:Como en un array el 1er elemento esta en la ubicacion 0.

mostrar_ubicacion::Ord a=>[a]->Int->a
mostrar_ubicacion l n = l!!n

Main> mostrar_ubicacion [15,25,26,28] 2
26

6.- Mayor elemento de una lista:

mayor::[Int]->Int
mayor (x:xs)
| x > mayor(xs) = x
| otherwise = mayor(xs)

Main> mayor [78,24,56,93,21,237,46,74,125]
237

Listas por comprensión: Son listas que no usan cabeza y cola, sino ciertos argumentos para definir los elementos que pertenecen a ella, de esta manera resolvemos problemas de una manera muy elegante y potente. Ejm: Le decimos a haskell que queremos una lista de elementos x, tales que x este en el rango de 1 a 12.

Main> [x | x <- [1 .. 12]]
[1,2,3,4,5,6,7,8,9,10,11,12]

Apliquemos esto a las operaciones con listas.

1.- Contar cuantos elementos pares hay en una lista. Estamos diciendo que x pertenece a la lista y ademas debe cumplir la condición de ser par. Como en varios lenguajes el length cuenta los elementos.

contarpares::[Int]->Int
contarpares []=0
contarpares lista= length [x | x <- lista, mod x 2 ==0]

Main> contarpares [5,4,7,8]
2

2.- Devolver los cuadrados de una lista:

cuadrados::[Int]->[Int]
cuadrados [ ] = [ ]
cuadrados l = [x*x| x <- l]

Main> cuadrados [1..10]
[1,4,9,16,25,36,49,64,81,100]

3.- Devolver una lista de  numeros primos de 1 a n: Para ello debemos crear nuestra funcion para saber si un numero es primo o no y despues la aplicamos a la lista por comprensión:

divisible::Int->Int->Bool
divisible x y = (mod x y) ==0

divisibles::Int->[Int]
divisibles x = [y | y <-[1..x],divisible x y]

esPrimo::Int->Bool
esPrimo n = length (divisibles n) <=2

primos::Int->[Int]
primos n = [x | x <-[1..n],esPrimo x]

Main> primos 100
[1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]

Gracias por tu visita al blog. Puedes seguirme en Twitter haciendo click en el siguiente enlace:

Written by Ronny Yabar

December 6, 2007 at 6:17 pm

19 Responses

Subscribe to comments with RSS.

  1. un pequeño fallo, el 1 no sale en la lista, ya que la condicion es que se hayan contado solo dos numeros que dividen exactamente al numero ( los primos solo son divisibles por ellos mismo y por el uno ) , pero claro, el 1 solo se divide por el mismo, por lo que solo se cuenta 1 vez

    luego habria que cambiar la condicion ‘==’ por ‘<=’ y el uno ya sale en la lista ^_^

    gracias por hacer este blog, me esta ayudando mucho con mis practicas en la facultad !

    vico

    March 31, 2008 at 2:37 am

  2. muy buen trabajo, ya que se presenta buena informacion acerca de las listas de haskell

    ismael

    April 28, 2008 at 3:56 pm

  3. Hola,soy un principiante con haskell. Estoy cursando paradigma y no se como hacer para ingresar o complilar los ejemplos,si sos muy amable me podes explicar como hacerlo…. Otra es que no tengo irea como hacer una lista de caracteres,a los pares pasarlos a mayuscula y a los impares en minuscula y como concatenar dos listas,si podes haceme el favor de darme una ayuda.muchas gracias y que dios te bendiga… contestame lo mas antes posible.Muchisimas gracias…

    david

    September 24, 2008 at 12:46 am

  4. necesito saber que significa la barra vertical que figura despues de x contarpares lista= length [x | x <- lista, mod x 2 ==0]
    estoy estudiando en la Tecnologica de Tucuman. Gracias por todo

    alejandra

    October 8, 2008 at 2:04 pm

  5. David Los ejemplos puedes probarlos con el intérprete hugs, que está disponible para múltiples plataformas (Linux, Mac, Windows, etc).
    No te entendí muy bien sobre lo de conversión de caracteres pares o impares podrías ser más explícito.

    En el caso de concatenar 2 listas es simple: Aquí está el código.

    conc_lists::[a]->[a]->[a]
    conc_lists xs [] = xs
    conc_lists [] ys = ys
    conc_lists (x:xs) (y:ys) = x: (conc_lists xs (y:ys))

    Ejemplo:

    Main> conc_lists[1,2,3][4,5,6]
    [1,2,3,4,5,6]

    Te lo explico brevemente:

    Tu función se llama conc_list, Primero declaras tus argumentos de entrada y salida.

    Recibes una lista, otra lista y te da como resultado igualmente una lista concatenada. Preguntas si alguna de las listas en vacía, si es así devuelve la otra lista.

    Por último, tomamos las 2 listas y empezamos a concatenar la cabeza de la lista 1 y empezamos a llamar recursivamente a la función para que concatene la cola de la lista 1 con los elementos de la lista 2.

    Tienes que tener bien en claro, lo que es la cabeza y cola de la lista y lo que significa recursión (una función que se llama así misma).

    Espero te sirva, cualquier consulta avisas. Saludos

    ronnyml

    October 29, 2008 at 4:42 am

  6. Alejandra la barra vertical indica la condición que debe cumplir la misma variable x para poder ser tomada en cuenta por la función length. Es como una asignación a lo que debe ser x.

    En este caso se leería x tal que x pertenece a la variable lista y además de ello que cumpla con la condición de que su división entre 2 de como residuo cero.

    Espero aclare tu duda. Saludos

    ronnyml

    October 29, 2008 at 4:56 am

  7. hola! estaba viendo el ejemplo de como buscar el mayor elemento de una lista, y lo transcribi en el archivo de winhugs.cuando lo ejecute , me daba un error. y era por que le falta agregar la condicion, de que si la lista esta vacia, el resultado debe de ser cero. seria lo siguiente:

    mayor::[Int]->Int
    mayor [ ] = 0
    mayor (x:xs)
    | x > mayor(xs) = x
    | otherwise = mayor(xs)

    gracias!!! los ejemplos me sirvieron de mucho!!

    anasol

    August 3, 2009 at 7:00 pm

  8. Para concatenar listas en una lista de listas en el entorno hugs es posible emplear “concat”, que concatena listas de la siguiente manera:
    main>concat [[1,2,3],[5,4,2]]
    main>[1,2,3,5,4,2]
    Talves prodrias encontrar algunos ejemplos en :
    http://www.program.webcindario.com/codigos/haskell.html
    en esa página hay algunos ejemplos

    John

    August 14, 2009 at 1:56 pm

  9. Interesante aporte ronnyl
    Las listas nos permiten estructurar de una mejor manera nuestros datos.

    Marck

    September 15, 2009 at 3:25 pm

  10. Gracias ronnyl por tus consejos, espero que sigas publicando mas articulos, que a muchos nos sirve bastante

    maria

    October 2, 2009 at 4:02 pm

  11. hola, necesitaria una ayuda…tengo un ejercisio que no lo puedo hacer..pude hacerlo pero usando dos funciones mas que prediseñe…quisiera saber si se puede hacer este ejercisio en una función:
    “Implementar en Haskell una función que dada una lista de enteros, devuelva una única tupla con dos listas con los números discriminados en función de un criterio dado como argumento (Función lógica).”

    yo el criterio que elegí fue pasar la lista y un número y q discrimine en multiplos o no(con mod x n)
    [Int] -> Int -> ([Int],[Int])

    gracias

    Rubén

    November 11, 2009 at 2:39 am

  12. Ese ejercicio lo podes resolver asi:
    funcion ::[Int]->([Int],[Int])
    funcion [] = ([],[])
    funcion (x:xs)
    |x>5 = (x:a,b)
    |otherwise = (a,x:b)
    where (a,b) = funcion xs
    Vos podes cambiarle la funcion logica y hacer con el mod x 2,pero seria una solucion a tu ejercicio.

    Cynthia

    November 24, 2009 at 5:41 pm

  13. Tengo un ejercicio en Haskell q me pideque rote los elemento de la lista dado un valor si es positivo hacia la izquiera y si es negativo hacia la derecha.Por ejemplo: [1,2,3,4] 2-> [4,3,1,2]
    [1,2,3,4] -1 -> [2,3,4,1]
    la 1º parte la resolvi pero no se como plantear la 2º
    rota:: Int->[a]->[a]
    rota n xs = drop n xs ++ take n xs

    Cynthia

    November 24, 2009 at 5:44 pm

  14. Hola!! Un gran artículo, sirve de mucha ayuda para los que estamos iniciándonos en el conocimiento del lenguaje Haskell.

    Tengo una duda, muy simple de realizar seguramente, pero para mi que soy un novato no tengo muy claro como realizarlo. Es un ejercicio en el que tengo que definir una función partir que divida una lista en dos mitades con el mismo número de elementos (+- 1). Alguien podría ayudarme?¿ Lo agradecería mucho.

    Un saludo!!

    Jose

    December 2, 2009 at 10:32 am

  15. Hola , muy buen post !

    Un pequeño detalle para el punto 6 .

    Falta una expresion para machear la lista vacia ,
    porque sino cuando llegues al final de la lista va a explotar porque no puede machear [] con (x:xs) . O en el caso de que hagas : mayor [] tambien dara error de macheo.

    entonces podria quedar:
    mayor [] = 0
    mayor (x:xs) | x > mayor(xs) = x
    | otherwise = mayor(xs)

    Saludos
    Pablo

    pablo

    July 20, 2010 at 10:14 pm

  16. Estoy empezando a utilizar este lenguaje, y me encontre con este post que me parecio muy bueno, muchas gracias espero que sigas publicando

    marco antonio

    August 10, 2010 at 12:38 pm

  17. en anterior oportunidad me dieron una tarea para hacer una lista y no tenia ni idea y fui buscando y me encontre con esto gracias ronyl.

    marco antonio

    August 10, 2010 at 12:42 pm

  18. ¡Hola! Excelente tutorial introductorio a Haskell. Realmente me sirvió muchísimo para hacer algunas definiciones recursivas para un trabajo universitario de lenguajes formales.
    Les quería agradecer, y de paso dejarles las definiciones (son muy sencillas por cierto, no esperen la gran cosa… pero bueno, quizá a alguien le sirva).

    Definiciones Haskell

    Saludos, y muchas gracias nuevamente

    vKmC

    October 28, 2010 at 8:00 am

  19. — Jugando con Matrices

    type Matrix = [[Int]]

    isM :: Matrix -> Bool
    isM ys = ((length ys) == length [ x | x 0)

    sqrM :: Matrix -> Bool
    sqrM xs | isM xs = length (head xs) == length xs
    | otherwise = error “Not even a Matrix!!! , you idiot.”

    detM2 :: Matrix -> Int
    detM2 xs | sqrM xs && (length (xs) == 2) = ((head (head xs)) * (last (last xs))) – ((head (last xs)) * (last (head xs)))
    | sqrM xs = error “Not a 2×2 Matrix”
    | otherwise = error “No determinant, Matrix is not a square.”

    detM3 :: Matrix -> Int
    detM3 [[a,b,c],[d,e,f],[g,h,i]] = a * (detM2 [[e,f],[h,i]]) + d * (detM2 [[h,i],[b,c]]) + g * (detM2 [[b,c],[e,f]])

    detM :: Matrix -> Int
    detM xs = detMaux (length xs) xs

    detMaux :: Int -> Matrix -> Int
    detMaux n xs | sqrM xs , n == 1 = head (head xs)
    | sqrM xs , n == 2 = detM2 xs
    | sqrM xs , n >= 3 , odd n = sum [ x * (detMaux (n-1) (y)) | (x,y) = 4 , even n = sum [ x * (detMaux (n-1) (y)) | (x,y) [(Int,Matrix)]
    sortit xs = hs xs (length xs)
    where hs :: Matrix -> Int -> [(Int,Matrix)]
    hs xs 0 = []
    hs xs n = (head (head xs),(tails xs)) : hs (rotateR 1 xs) (n-1)

    rotateR :: Int -> [a] -> [a]
    rotateR n xs = (drop n xs) ++ (take n xs)

    rotateC :: Int -> Matrix -> Matrix
    rotateC n xs = [ rotateR n x | x [(Int,Matrix)]
    oneyes [] = []
    oneyes ((x,y):xs) | odd (length ((x,y):xs)) = (-x,y) : oneyes (xs)
    | even (length ((x,y):xs)) = (x,y) : oneyes (xs)

    oneyes2 :: [Int] -> [Int]
    oneyes2 [] = []
    oneyes2 (x:xs) | odd (length (x:xs)) = -x : oneyes2 (xs)
    | even (length (x:xs)) = x : oneyes2 (xs)

    tails :: Matrix -> Matrix
    tails xs = [ tail x | x Matrix
    invM xs | sqrM xs && (detM xs /= 0) = invMaux xs (length xs) 0
    | sqrM xs && (detM xs == 0) = error “No inverse , Matrix determinant equals zero.”
    | otherwise = error “Non-square Matrix.”

    invMaux :: Matrix -> Int -> Int -> Matrix
    invMaux ps 0 m = []
    invMaux (p:ps) n m = [ term w l (p:ps) | (w,l,k) <- ((locationaux3 (p:ps)) !! m)] : invMaux (p:ps) (n-1) (m+1)
    where locationaux ys = zip [1..] ys
    locationaux2 xs = locationaux [ locationaux x | x <- xs]
    putin (j,ms) = [ (j,i,m) | (i,m) <- ms]
    locationaux3 zs = [ putin z | z Int -> Matrix -> Int
    term i j xs = div (((-1)^(i+j)) * (detM (two i j xs))) (detM xs)
    where one k xs = (take (k-1) xs) ++ (drop k xs)
    two i j xs = [ one i x | x <- (one j xs)]

    — El objetivo era hacer la inversa!!!

    Brennan

    October 19, 2014 at 11:47 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: