Está en la página 1de 15

Haskell

PDF generado usando el kit de herramientas de fuente abierta mwlib. Ver http://code.pediapress.com/ para mayor informacin. PDF generated at: Sun, 06 Nov 2011 19:54:52 UTC

Contenidos
Artculos
Haskell Hugs Glasgow Haskell Compiler QuickCheck 1 6 6 7

Referencias
Fuentes y contribuyentes del artculo 12

Licencias de artculos
Licencia 13

Haskell

Haskell
Haskell Informacin general Paradigma Apareci en Diseado por Tipo de dato Funcional, no estricto, modular, fuertemente tipificado 1990 Universidad de Yale, Universidad de Glasgow Fuerte, esttico

Implementaciones GHC, Hugs, NHC, Yhc, JHC Influido por Ha influido a Miranda, ML, Gofer Python

Haskell es un lenguaje de programacin puramente funcional de propsito general y fuertemente tipado. Su nombre proviene del lgico Haskell Curry. En los aos 1980 se constituy un comit cuyo objetivo era crear un lenguaje funcional que reuniera las caractersticas de los mltiples lenguajes funcionales de la poca, el ms notable Miranda, y resolviera la confusin creada por la proliferacin de los mismos. El lenguaje evoluciona rpidamente con y (ver ms abajo) como los representantes actuales del estndar de facto. El ltimo estndar semi-oficial es Haskell 98, con la intencin de especificar una versin mnima y compatible del lenguaje como base para futuras extensiones y para su enseanza. Las caractersticas ms interesantes de Haskell incluyen el soporte para tipos de datos y funciones recursivas, listas, tuplas, guardas y calce de patrones. La combinacin de las mismas pueden resultar en algunas funciones casi triviales cuya versin en lenguajes imperativos pueden llegar a resultar extremadamente tediosas de programar. Haskell es, desde 2002, uno de los lenguajes funcionales sobre los que ms se ha investigado. Se han desarrollado muchas variantes: Versiones paralelas del MIT y Glasgow, ambas denominadas Parallel Haskell. Ms versiones paralelas y distribuidas de Haskell llamadas Distributed Haskell (anteriormente Goffin) y Eden Una versin con ejecucin especulativa: Eager Haskell Varias versiones orientadas a objetos: Haskell++, O'Haskell y Mondrian. Una versin educativa llamada Gofer desarrollada por Mark Jones que fue suplantada por Hugs (ver abajo).

Para informacin ms detallada, referirse al sitio oficial o a los links al final de este artculo.

Historia
A partir de la publicacin de Miranda, en 1985, los lenguajes funcionales proliferaron. En 1987, existan compitiendo entre llos ms de una docena de lenguajes de programacin puros funcionales no estrictos. Durante la conferencia sobre Lenguajes de Programacin Funcional y Arquitecturas de Ordenador (FPCA '87) en Portland, Oregn, se mantuvo un meeting durante el cual se alcanz un fuerte consenso entre sus participantes para formar un comit que definiese un estndar abierto para tales lenguajes. Esto se hizo con el propsito expreso de consolidar los lenguajes existentes en uno nico que sirviera como base para la investigacin futura en diseo de lenguajes.[1] La primera versin de Haskell ("Haskell 1.0") se defini en 1990.[2] Los esfuerzos del comit resultaron en una serie de definiciones del lenguaje, que culminaron a finales de 1997 en Haskell 98, que se intent fuera una versin del lenguaje mnima, estable y portable, junto con una biblioteca estndar asociada para la enseanza, y como base de futuras extensiones. El comit expresamente aprob la creacin de extensiones y variantes de Haskell 98 mediante la adicin e incorporacin de caractersticas experimentales.

Haskell En enero de 1999, el estndar del lenguaje Haskell 98 se public en "The Haskell 98 Report". En enero de 2003, se public una versin revisada en "Haskell 98 Language and Libraries: The Revised Report".[3] El lenguaje contina evolucionando rpidamente, con las implementaciones de Hugs y de GHC (vase ms adelante), que representan el actual estndar de facto. A principios del 2006 comenz el proceso de definicin de un sucesor del estndar de Haskell 98, llamado informalmente Haskell ("Haskell Prime").[4] Este proceso intenta producir una revisin menor de Haskell 98.[5]

Tipos simples predefinidos


El tipo Bool
Los valores con este tipo representan expresiones lgicas cuyo resultado puede ser True o False. Funciones y operadores (&&) :: Bool -> Bool -> Bool. Conjuncin lgica. (||) :: Bool -> Bool -> Bool. Disyuncin lgica. not :: Bool -> Bool. Negacin lgica. otherwise :: Bool. Funcin constante que devuelve el valor True.

El tipo Int
Los valores de este tipo son nmeros enteros de precisin limitada que cubren al menos el intervalo [-2^29, 2^29 - 1] ([minBound, maxBound]). fun multi(p1: real list,p2:real list)= let fun mult((p1),([]),(l3),(i))=p1; fun mult(([]),(p2),(l3),(i))=p2; fun mult(x::xs),(y::ys),(l3),(i)) = if i =length (ys) then l3 else (x * y)::mult((x),(ys),(l3),(i+1)) in crea(mult((l1),(l2),([]),(0))) end;

El tipo Integer
Los valores de este tipo son nmeros enteros de precisin ilimitada que tienen las mismas funciones y operadores del tipo Int.

El tipo Float
Los valores de este tipo son nmeros reales. ( 2010, 23.4 , 5.7 ) Funciones y operadores (+), (-), (*), (/), (^):: Float -> Float -> Float. Suma, resta, producto, divisin real y potencia de exponente entero. abs, signum, negate :: Int -> Int. Valor absoluto, signo y negacin. (**) :: Float -> Float. Potencia de exponente real

Haskell

El tipo Double
Los valores de este tipo son nmeros reales, de mayor rango y con aproximaciones ms precisas que los de tipo Float.

El tipo Char
Los valores de este tipo son caracteres que se encuentran en una masa de alta complejidad de en una suma de caracteres dados con su alta definicin Antes de utilizar esta funcin en hugs debemos utilizar IMPORT CHAR antes de nuestro algoritmo

Tuplas
Los elementos que forman una tupla pueden ser de distintos tipos. Por ejemplo: ('a',True,3)

Listas
Los valores de este tipo son una coleccin de elementos del mismo tipo. Existen dos constructoras para listas: [Elementos_separados_por_comas] , por ejemplo: [1,2,3,4] (primer_elemento:resto_de_la_lista) , por ejemplo: (1:(2:(3:(4:[]))))

Implementaciones
Todas las siguientes implementaciones cumplen en su totalidad, o casi en su totalidad, con los estndares de Haskell 98 y son distribuidas bajo licencias Open Source. No se conocen implementaciones comerciales del lenguaje. Hugs ([6]) es un intrprete. Ofrece una compilacin rpida de los programas y un tiempo razonable de ejecucin. Tambin viene con una librera grfica muy simple, lo que lo hace adecuado para quienes lo estn aprendiendo. Sin embargo no es una implementacin a despreciar, es una de las ms livianas y compatibles. GHC ([7]): "Glasgow Haskell Compiler" compila a cdigo nativo en una variedad de arquitecturas y puede tambin compilar a C. Es, probablemente, uno de los compiladores ms populares e incluso tiene unas cuantas libreras (por ejemplo OpenGL) que, aunque muy tiles, slo funcionan bajo GHC. nhc98 ([8]) es otro compilador con un mejor tiempo de ejecucin que Hugs. Esta implementacin se enfoc a minimizar la utilizacin de la memoria convirtindola en una buena opcin para arquitecturas lentas o antiguas. HBC ([9]) es otro compilador a cdigo nativo de Haskell. Si bien no ha sido actualizado en el ltimo tiempo sigue siendo bastante til. Helium ([10]) es un nuevo dialecto de Haskell. Se centr en ser muy fcil de aprender; por ello, no incluye soporte para todo el estndar de Haskell, haciendo que no sea totalmente compatible.

Ejemplos
--Funcin recursiva para calcular el factorial de un nmero factorial :: Integer -> Integer factorial n = if n==0 then 1 else n * factorial (n - 1) --Sumar elementos de una lista sumar :: [Int] -> Int

Haskell sumar [] = 0 sumar (x:xs) = x+sumar(xs) --Funcin pseudnimos factorial factorial factorial recursiva para calcular el factorial de un nmero usando :: Integer -> Integer 0 = 1 m@(n + 1) = m * factorial n

--Funcin para calcular las races de una ecuacin de segundo grado a partir de sus coeficientes races :: Float -> Float -> Float -> (Float, Float) races a b c | disc >= 0 = ((-b + raizDisc) / denom, (-b - raizDisc) / denom) | otherwise = error "La ecuacin tiene races complejas" where disc = b*b - 4*a*c raizDisc = sqrt disc denom = 2*a --Funcin para calcular el valor de e (2.71828182845905) euler :: Double -> Double euler 0.0 = 1.0 euler n = 1.0 / product [1..n] + euler (n - 1.0) --Algoritmo de ordenacin quicksort qs::Ord a=>[a]->[a] qs [] = [] qs (p:xs) = qs [x|x<-xs,x<p] ++ [p] ++ qs [x|x<-xs,x>=p] --Funcin para calcular el mximo comn divisor mediante el algoritmo de Euclides mcd::Int->Int->Int mcd x 0 = x mcd x y = mcd y (mod x y) -- Criba de eratostenes (de una lista dada [2..n] t deja solo los numeros primos) eratostenes :: [Int] -> [Int] eratostenes [] = [] eratostenes (x:xs) | not (null xs) && x^2 > last xs = (x:xs) | otherwise = x: eratostenes [y | y <- xs, y `mod` x /= 0]

Haskell

Vase tambin
QuickCheck

Referencias
[1] Preface (http:/ / haskell. org/ onlinereport/ preface-jfp. html). Haskell 98 Language and Libraries: The Revised Report (December de 2002). [2] The History of Haskell (http:/ / www. haskell. org/ haskell-history. html). [3] Simon Peyton Jones (December de 2002). Haskell 98 Language and Libraries: The Revised Report (http:/ / haskell. org/ onlinereport/ ). [4] Future development of Haskell (http:/ / haskell. org/ haskellwiki/ Future). [5] Welcome to Haskell' (http:/ / hackage. haskell. org/ trac/ haskell-prime). The Haskell' Wiki. [6] http:/ / www. haskell. org/ hugs/ [7] http:/ / www. haskell. org/ ghc/ [8] http:/ / www. cs. york. ac. uk/ fp/ nhc98/ [9] http:/ / www. cs. chalmers. se/ ~augustss/ hbc/ hbc. html [10] http:/ / www. cs. uu. nl/ helium/

Enlaces externos
Ingls: Haskell (http://www.haskell.org) Pgina oficial de Haskell A Gentle Introduction to Haskell 98 (http://www.haskell.org/tutorial/) ( pdf (http://www.haskell.org/ tutorial/haskell-98-tutorial.pdf) format) Una simple introduccin a Haskell 98 The Evolution of a Haskell Programmer (http://www.willamette.edu/~fruehr/haskell/evolution.html) Una forma cmica de ver los distintos estilos de programacin en Haskell Online Bibliography of Haskell Research (http://haskell.readscheme.org) Bibliografa de investigaciones en Haskell Haskell (programming language) Learn You a Haskell for Great Good (http://learnyouahaskell.com/) Espaol: Introduccin a Haskell (http://horru.lsi.uniovi.es/~labra/FTP/IntHaskell98.pdf) Lenguaje de Programacin Funcional Haskell (http://www.frt.utn.edu.ar/sistemas/paradigmas/Haskell.htm) Haskell Bsico Una Introduccin Agradable a Haskell (http://www.lcc.uma.es/~blas/pfHaskell/gentle/index.html) Versin en espaol del libro "A Gentle Introduction to Haskell". Aprende Haskell por el bien de todos! (http://aprendehaskell.es/) Traduccin de la obra "Learn you a Haskell for great good". Implementaciones: Hugs (http://haskell.org/hugs/) Haskell User's Gofer System GHC (http://haskell.org/ghc/) The Glasgow Haskell Compiler Helium (http://www.cs.uu.nl/wiki/Helium), Helium

Bibliografa
Ruiz, Blas; Gutirrez, Francisco; Guerrero, Pablo; y Gallardo, Jos. Razonando con Haskell. Un curso sobre programacin funcional. Thomson.

Hugs

Hugs
Hugs (Haskell User's Gofer System) es un intrprete bytecode para el lenguaje funcional Haskell. Ofrece compilacin rpida y una velocidad de ejecucin aceptable. Adems, se obtiene con una biblioteca grfica simple. Hugs es una buena herramienta para toda aquel que est aprendiendo las bases de Haskell, lo cual no implica que sea una "implementacin de juguete". Es la ms portable y ligera de todas las implementaciones de Haskell. Hugs es un programa de cdigo abierto que dispone de versiones para los sistemas operativos ms difundidos tales como Linux, BSD, Microsoft Windows o Mac OS X.

Enlaces externos
Pgina oficial de Hugs [1]

Referencias
[1] http:/ / www. haskell. org/ hugs

Glasgow Haskell Compiler


Glasgow Haskell Compiler Desarrollador Universidad de Glasgow http:/ / www. haskell. org/ ghc'' Informacin general ltima versin estable 7.2.1 9 de septiembre de 2011 Gnero Programado en Sistema operativo Licencia En espaol Compilador Haskell, C Multiplataforma BSD ? [1]

El Glasgow Haskell Compiler (o GHC) es un compilador nativo de cdigo libre para el lenguaje de programacin funcional Haskell, que fue originalmente desarrollado en la Universidad de Glasgow, en un principio por Simon Peyton Jones y Simon Marlow. El desarrollo contina bajo el auspcio del Departamento de Investigacin de Microsoft (Microsoft Research), en el Reino Unido, donde estn empleados Peyton Jones y Marlow. GHC ha tomado humorsticamente el apodo "Glorious Haskell Compiler". El compilador tambin est escrito en Haskell (una tcnica conocida como bootstrapping), pero el ncleo de sistema para Haskell est escrito en C y C--. La ltima versin del compilador cumple con Haskell 98, el estndar ms reciente del lenguaje. GHC est disponible para muchas plataformas, incluyendo Windows y la mayora de sistemas Unix (como las diferentes distribuciones de GNU/Linux), Mac OS X y la mayora de arquitecturas de procesador. GHC incluye la mayora de extensiones de Haskell estndar, incluyendo la biblioteca STM, que sirve para permitir las transacciones de datos directamente con la memoria.

Glasgow Haskell Compiler

Referencias
[1] The Glasgow Haskell Compiler License (http:/ / www. haskell. org/ ghc/ license. html) (en ingls)

Enlaces externos
Pgina oficial de GHC (http://www.haskell.org/ghc) (en ingls)

QuickCheck
QuickCheck es una herramienta que el lenguaje de programacin Haskell provee para poder probar las propiedades que deberan de cumplir las funciones, es decir, cada funcin tiene propiedades deseables lo que se logra con QuickCheck es ver si se cumplen total o parcialmente estas propiedades. Una ventaja notoria es que la propiedad es probada con una gran cantidad de casos generados aleatoriamente. Por ejemplo si tenemos una funcin suma: suma x y = x + y para ver si cumple la propiedad conmutativa de la suma de nmeros enteros, para cualquier entero: prop_suma_conmutativa :: Int ->Int -> Bool prop_suma_conmutativa x y = suma x y == suma y x la funcin prop_suma_conmutativa al ser pasada como parmetro en quickCheck ser verificada con varios casos aleatorios de enteros e indicar si eventualmente la funcin suma cumple o no la propiedad de la suma de nmeros enteros. Detalles Tericos importantes QuickCheck toma como parmetro de entrada una propiedad Las propiedades son un conjunto de afirmaciones parametrizadas que en Haskell son funciones normales que pueden ser entendidas por cualquier compilador o interprete Estas propiedades son verificadas con un nmero grande de casos de prueba generados de forma aleatoria Los programadores controlan la distribucin de los casos de prueba generados con reglas condicionales y generadores Permite programar generadores propios Las funciones que deseamos probar pueden ser polimrficas pero las propiedades a probar deben ser monomrficas. El siguiente ejemplo muestra un error, por esto: import Test.QuickCheck insertOrdered :: (Ord a) => a -> [a] -> [a] insertOrdered a [] = [a] insertOrdered a (x:xs)| a <= x = a:[x] ++ xs | a > x = x: insertOrdered a xs prop_insertOrdered a (xs) = ordered(insertOrdered a xs) -- main = quickCheck prop_insertOrdered >:l Main Main> quickCheck prop_insertOrdered ERROR - Unresolved overloading Notar en este ejemplo:

QuickCheck El nombre de la funcin para probar la propiedad, comienza con el prefijo prop_ (Ej. prop insertOrdered)esto es por convencin. Se us una funcin auxiliar ordered para probar la propiedad Podemos llamar la funcin quickCheck tanto en la lnea de comandos como dentro de nuestro programa. Otro punto interesante a notar es que inclusive luego de aadir el tipo a la funcin, devuelve el siguiente mensaje Falsifiable, after 3 tests

Combinadores provistos por QuickCheck


Combinador condicional: Podemos mejorar un poco el ejemplo anterior aadiendo una condicin, a nuestra propiedad. prop_InsertOrdered :: Integer -> [Integer] -> Property prop_InsertOrdered x xs = ordered xs ==> ordered (insertOrdered x xs []) La estructura para utilizar el combinador condicional: <condition> ==> <property> La introduccin del combinador condicional ==> nos indica que solo se intentara probar la propiedad con casos que satisfagan la condicin, si un candidato no satisface la condicin es descartado y se probara con otro. Ahora el tipo devuelto de la funcin es Property Algunas veces la propiedad que es probada con condiciones, saca este mensaje Arguments exhausted after 55 tests. Esto suele suceder si la condicin no es satisfecha y se han producido muchos casos que no satisfacen la propiedad, nos indica que por lo menos 55 casos pasaron la prueba, el programador decide aqu si esto es suficiente o no. Combinador classify: El combinador classify no cambia el significado de la propiedad pero permite clasificar algunos casos, se podra decir que es una forma de etiquetarlos. En el ejemplo anterior veamos la cantidad de listas producidas aleatoriamente de tamao menor a uno y listas mayores de dos elementos. prop_InsertOrdered :: Int -> [Int] -> Property prop_InsertOrdered x xs = ordered xs ==> classify (length xs <= 1) "lista de tam < 1" $ classify (length xs > 2) "lista de tam > 2" $ ordered (insertOrdered x xs) *Main> main OK, passed 100 tests. 79% lista de tam < 1. 4 % lista de tam > 2. *Main> La estructura para utilizar el combinador classify: classify <condition><string>$ <property> Como vemos solo un 4% de las listas generadas aleatoriamente son de tamao mayor a dos. Combinador collect: El combinador collect cosecha todos los valores que son pasados e imprime un histograma de esos, aqu podemos darnos cuenta que solo un porcentaje menor de casos de prueba son probados porque (en el caso especfico) las listas de 1 o 0 elementos son ordenados pero los mayores a 2 elementos no lo son, este es un riesgo al utilizar leyes condicionales.

QuickCheck prop_InsertOrdered :: Int -> [Int] -> Property prop_InsertOrdered x xs = ordered xs ==> collect (length xs >1)$ collect (length xs)$ ordered (insertOrdered x xs) *Main> main OK, passed 100 tests. 49% False, 0. 34% False, 1. 13% True, 2. 3% True, 3. 1% True, 4. La estructura para utilizar el combinador collect: collect <expression> $ <property> Es importante investigar la proporcin de los casos probados Lo que nos indica la salida es que: 49% de los casos no cumplen la expresin (length xs > 1) porque su tamano es 0,34% de los casos no cumplen la expresin (length xs > 1) porque su tamano es 1, etc. Una solucin es que le pasemos un generador de listas ordenadas quickcheck nos facilita esto, al permitirnos crear generadores propios. Combinador forAll: El combinador forAll nos indica que para toda lista ordenada se podr probar la propiedad. prop_InsertOrdered :: Integer -> Property prop_InsertOrdered x = forAll orderedList $ \ xs -> collect (length xs>2)$ collect (length xs)$ ordered (insertOrdered x xs) -- el generador de listas ordenadas, -- solo es una funcion que crea listas ordenadas orderedList :: (Ord a, Arbitrary a) => Gen [a] orderedList = frequency [(1,return []), (4,do xs <- orderedList n <- arbitrary return ((case xs of [] -> n x:_ -> n min x) :xs))] Main> main OK, passed 100 tests. 18% False, 1. 16% False, 0. 15% False, 2. 10% True, 8. 10% True, 3.

QuickCheck 8% 5% 4% 4% 3% 2% 2% 2% 1% True, True, True, True, True, True, True, True, True, 4. 5. 9. 13. 6. 7. 11. 10. 16.

10

La estructura para utilizar el combinador forAll: forAll <generator>$\<pattern> -> <property> La salida nos indica que el 18% de las listas generadas aleatoriamente, por nuestro generador no es mayor a dos, su tamao es uno, que el 1% de los casos generados por la funcion orderedList(que genera listas ordenadas) si es mayor a dos y su tamano es 16. Notar que utilizamos el combinador frequency Solo observando: Veamos la distribucin de los casos de prueba... prop_InsertOrdered :: Integer -> [Integer] -> Property prop_InsertOrdered x xs = ordered xs ==> (length xs <= 1) trivial ordered (insertOrdered x xs) *Main> main OK, passed 100 tests (86% trivial). La estructura para ver la distribucin es: <condition> trivial <property> Indicamos que las listas generadas por la funcion orderedList son triviales en aquellos casos que su tamao sea menor o igual a uno La respuesta nos dice que el 86% de los casos son triviales. Definiendo Generadores Propios Para definir generadores propios para nuestros tipos de datos utilizamos la Clase Arbitrary. data Insectos = Polillas | Mariposas | OtrosBichos instance Arbitrary Insectos where arbitrary = oneof [ return Mariposas, return Polillas , return OtrosBichos] oneof: Podemos utilizar el combinador oneof escoge de una lista de generadores alternativos con una distribucin uniforme, los constructores. frequency: Veamos la siguiente estructura, un rbol binario con dos funciones tam que nos devuelve el tamao del rbol y arbolALista que nos devuelve los elementos de un rbol en una lista. module ArbolBin where import Test.QuickCheck

QuickCheck import Control.Monad -- necesitamos para la funciones -- liftM, liftM2 data ArbolBin a = Hoja a | Rama (ArbolBin a ) (ArbolBin a ) deriving Show tam :: ArbolBin Int -> Int tam (Hoja a) = 1 tam (Rama i d) = tam i + tam d arbolALista :: ArbolBin Int -> [Int] arbolALista (Hoja x) = [x] arbolALista (Rama i d )= arbolALista i ++ arbolALista d Una propiedad que nos gustara que cumpla la funcin arbolALista es que el tamao de la lista sea igual al tamao del rbol. prop_arbolALista:: ArbolBin Int -> Bool prop_arbolALista t = length (arbolALista t )== tam t instance Arbitrary a => Arbitrary (ArbolBin a) where arbitrary = frequency [ (1,liftM Hoja arbitrary ), (2,liftM2 Rama arbitrary arbitrary )] main = quickCheck prop_arbolALista El combinador frequency, que vimos anteriormente es del tipo: frequency :: [(Int, Gen a)] -> Gen a Su tipo nos dice que recibe una lista de generadores. Como primer parmetro la frecuencia con la que se escoger cada generador y como segundo el generador en si. En el ejemplo del rbol binario se escoger dos veces el generador para Rama y solo uno (de cada dos) para el generador de Hoja. En el ejemplo para la insercin para el combinador forAll nos dice que escoger cuatro veces una lista diferente de vaco([])y una vez una lista vaca ([]). Algo importante que hay que recalcar es que para utilizar de manera adecuada QuickCheck debemos saber que propiedades necesitamos que cumplan nuestras funciones. import Test.QuickCheck Definir Propiedades Opcionalmente definir generadores Main > quickCheck pro_definida

11

Fuentes y contribuyentes del artculo

12

Fuentes y contribuyentes del artculo


Haskell Fuente: http://es.wikipedia.org/w/index.php?oldid=49595852 Contribuyentes: Alexav8, CaStarCo, DefLog, Diablo Cris, Dodo, Elwikipedista, Emijrp, Fpina7, GermanX, Grace Pahuasi, HavokCR, Janus, JavierCantero, JoaquinFerrero, Jvillais, Makam, Matdrodes, MatiasBellone, Moriel, Muro de Aguas, Nueva era, Rbonvall, SanIctcola, Simeon87, Taty2007, Template namespace initialisation script, Tomatejc, Toranks, Triku, Wilson Fisk, 49 ediciones annimas Hugs Fuente: http://es.wikipedia.org/w/index.php?oldid=45883153 Contribuyentes: CaStarCo, Gothmog, Shooke Glasgow Haskell Compiler Fuente: http://es.wikipedia.org/w/index.php?oldid=48957170 Contribuyentes: Aleator, CaStarCo, GermanX, Locos epraix, Rbonvall, Simeon87 QuickCheck Fuente: http://es.wikipedia.org/w/index.php?oldid=34968028 Contribuyentes: Grace Pahuasi, Ignacio Icke, Libertad y Saber, Xareno, Xmc, Yrithinnd

Fuentes de imagen, Licencias y contribuyentes

13

Licencia
Creative Commons Attribution-Share Alike 3.0 Unported //creativecommons.org/licenses/by-sa/3.0/

También podría gustarte