Wikilibros
eswikibooks
https://es.wikibooks.org/wiki/Portada
MediaWiki 1.47.0-wmf.24
first-letter
Medio
Especial
Discusión
Usuario
Usuario discusión
Wikilibros
Wikilibros discusión
Archivo
Archivo discusión
MediaWiki
MediaWiki discusión
Plantilla
Plantilla discusión
Ayuda
Ayuda discusión
Categoría
Categoría discusión
TimedText
TimedText talk
Módulo
Módulo discusión
Evento
Evento discusión
Manual de LaTeX
0
2321
436566
431421
2026-10-15T07:52:34Z
Antimundo
74354
Categorizar usando estantes
436566
wikitext
text/x-wiki
[[Archivo:LaTeX2e_logo.svg|center|400px|{{LaTeX|2e}}]]
<div style="font-size:120%; text-align:center;">Te damos la bienvenida al libro de {{LaTeX|2e}}.</div>
Si deseas colaborar en este libro, te recomendamos que te pases por la [[Manual de LaTeX/Página de edición|página de edición]].
== Qué es LaTeX ==
Es un sistema de composición tipográfica basado en TeX, originalmente centrado en obras de contenido matemático, pero que actualmente abarca multitud de tipos de escritos. Tiene características tanto de un lenguaje de marcado como de uno de programación, y puede integrarse en sistemas de producción automática basados en XML (o SGML), Unicode, PDF...
Se basa en el principio del WYGIWYM, siglas inglesas de ''lo que se obtiene es lo que se quiere'', y se basa en crear un documento de texto con marcado lógico y semántico del que se genera un PDF (aunque hay otra opciones).
Es muy popular en contextos académicos científicos, pero no se limita a la creación de trabajos, tesis y presentaciones: también, fuera de este ámbito y en el mundo de la producción editorial, abarca la creación de catálogos o diccionarios partir de bases de datos, la producción libros de textos y documentación técnica..., todo ello en un contexto que abarca desde la escritura por el autor, liberado de la tarea del formato, pasando por la composición, hasta la imposición para la imprenta.
Además de la composición en sí, LaTeX permite, gracias a las herramientas y extensiones que suelen acompañarlo, elementos gráficos e ilustraciones (incluyendo CMYK, colores directos, perfiles ICC), generación de índices alfabéticos (uno o varios) y de contenido (general o por capítulos), bibliografías (según diversos estilos), notas al pie (o al margen o a final de capítulo), hiperenlaces internos y externos, elementos dinámicos (animaciones, gráficos interactivos)...
Pueden encontrarse ejemplos de publicaciones y otros documentos creados con LaTeX y programas asociados en:
* [http://tex.stackexchange.com/questions/1319/showcase-of-beautiful-typography-done-in-tex-friends Showcase of beautiful typography done in TeX & friends]
* [http://tex.stackexchange.com/questions/105621/beautiful-presentations-done-with-tex-and-related-systems?rq=1 Beautiful presentations done with TeX and related systems]
* [http://tex.stackexchange.com/questions/129274/showcase-of-optical-illusions-made-with-tex-latex-luatex-context Showcase of optical illusions made with TeX/LaTeX/LuaTeX/ConTeXt]
* [http://tex.stackexchange.com/questions/158668/nice-scientific-pictures-show-off Nice scientific pictures show off]
* [http://tex.stackexchange.com/questions/134638/showcase-tex-typography-for-tugs-calendar Showcase TeX Typography for TUG's Calendar]
== Índice ==
[[Manual de LaTeX/Datos preliminares|Capítulo 1. Datos preliminares]]
# [[Manual de LaTeX/Introducción/Introducción a LaTeX|Introducción a {{LaTeX}}]]
# [[Manual de LaTeX/Introducción/La escritura en LaTeX|La escritura en {{LaTeX}}]]
# [[Manual de LaTeX/Introducción/Instalación|Instalación]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en Linux|Instalación en Linux]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en OS X|Instalación en OS X]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en Windows|Instalación en Windows]]
# [[Manual de LaTeX/Introducción/Programas complementarios|Programas complementarios]]
[[Manual de LaTeX/La estructura de un documento en LaTeX|Capítulo 2. La estructura de un documento en {{LaTeX}}]]
# [[Manual de LaTeX/La estructura de un documento en LaTeX/El preámbulo y el cuerpo del documento|El preámbulo y el cuerpo del documento]]
# [[Manual de LaTeX/La estructura de un documento en LaTeX/Clases de documento y algunos paquetes comunes|Clases de documento y algunos paquetes comunes]]
[[Manual de LaTeX/Escribiendo texto|Capítulo 3. Escribiendo texto]]
# [[Manual de LaTeX/Escribiendo texto/Espacios|Espacios]]
# [[Manual de LaTeX/Escribiendo texto/Caracteres especiales|Caracteres especiales]]
# [[Manual de LaTeX/Escribiendo texto/Tamaños, estilos y tipos de letra|Tamaños, estilos y tipos de letra]]
# [[Manual de LaTeX/Escribiendo texto/Alineación del texto|Alineación del texto]]
# [[Manual de LaTeX/Escribiendo texto/Partición de palabras|Partición de palabras]]
# [[Manual de LaTeX/Escribiendo texto/Signos ortográficos|Signos ortográficos]]
# [[Manual de LaTeX/Escribiendo texto/Portada del documento|Portada del documento]]
# [[Manual de LaTeX/Escribiendo texto/Capítulos y secciones|Secciones de un documento]]
# [[Manual de LaTeX/Escribiendo texto/Estilos de página|Estilos de página]]
# [[Manual de LaTeX/Escribiendo texto/Referencias|Referencias]]
# [[Manual de LaTeX/Escribiendo texto/Notas al pie|Notas al pie]]
# [[Manual de LaTeX/Escribiendo texto/Listas|Listas]]
# [[Manual de LaTeX/Escribiendo texto/Citas|Citas]]
# [[Manual de LaTeX/Escribiendo texto/Tablas|Tablas]]
[[Manual de LaTeX/Fórmulas matemáticas|Capítulo 4. Fórmulas matemáticas]]
# [[Manual de LaTeX/Fórmulas matemáticas/Inserción de una fórmula|Inserción de una fórmula]]
# [[Manual de LaTeX/Fórmulas matemáticas/Símbolos matemáticos|Símbolos matemáticos]]
# [[Manual de LaTeX/Fórmulas matemáticas/Operadores|Operadores]]
# [[Manual de LaTeX/Fórmulas matemáticas/Superíndices y subíndices|Superíndices y subíndices]]
# [[Manual de LaTeX/Fórmulas matemáticas/Fracciones y binomios|Fracciones y binomios]]
# [[Manual de LaTeX/Fórmulas matemáticas/Raíces|Raíces]]
# [[Manual de LaTeX/Fórmulas matemáticas/Sumas e Integrales|Sumas e Integrales]]
# [[Manual de LaTeX/Fórmulas matemáticas/Delimitadores|Delimitadores]]
# [[Manual de LaTeX/Fórmulas matemáticas/Arreglos matemáticos|Arreglos matemáticos]]
# [[Manual de LaTeX/Fórmulas matemáticas/Texto entre matemáticas|Texto entre matemáticas]]
# [[Manual de LaTeX/Fórmulas matemáticas/Maneras para darle formato a los símbolos matemáticos|Maneras para darle formato a los símbolos matemáticos]]
# [[Manual de LaTeX/Fórmulas matemáticas/Control de espaciado horizontal|Control de espaciado horizontal]]
# [[Manual de LaTeX/Fórmulas matemáticas/Entornos para teoremas|Entornos para teoremas]]
[[Manual de LaTeX/Formulas matemáticas avanzadas|Capítulo 5. Formulas matemáticas avanzadas]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Numeración de ecuaciones|Numeración de ecuaciones]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Alineación vertical en matemáticas|Alineación vertical en matemáticas]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Ecuaciones particulares|Ecuaciones particulares]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Salto de páginas dentro de un entrono de matemáticas|Salto de páginas dentro de un entrono matemático]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Marco para resaltar una ecuación|Marco para resaltar una ecuación ]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Operadores personalizados|Operadores personalizados]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Configuración avanzada|Configuración avanzada]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Texto alineado en entorno matematico|Texto alineado en entorno matematico]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Cambio del tamaño de fuente|Cambio del tamaño de fuente]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Forzando \displaystyle en todo el documento|Forzando \displaystyle en todo el documento]]
# [[Manual de LaTeX/Formulas matemáticas avanzadas/Ajuste del espaciado vertical en el modo matemático|Ajuste del espaciado vertical en el modo matemático]]
[[Manual de LaTeX/Inclusión de gráficos|Capítulo 6. Gráficos]]
# [[Manual de LaTeX/Inclusión de gráficos/Objetos flotantes|Objetos flotantes]]
# [[Manual de LaTeX/Inclusión de gráficos/Subtítulos, Listas y referencias cruzadas|Subtítulos, Listas y referencias cruzadas ]]
# [[/Insertar figuras en un documento|Insertar figuras externas]]
# [[Manual de LaTeX/Inclusión de gráficos/Texto alrededor de figuras|Texto alrededor de figuras]]
# [[Manual de LaTeX/Inclusión de gráficos/Figuras en varias partes y en dos columnas|Figuras en varias partes y en dos columnas]]
# [[Manual de LaTeX/Inclusión de gráficos/Introduccion a dibujos de gráficos en LaTeX|Introducción a dibujos de gráficos en {{LaTeX}}]]
# [[Manual de LaTeX/Inclusión de gráficos/ Graficos con picture | Graficos con {{LaTeX/Environment|picture}} ]]
# [[Manual de LaTeX/Inclusión de gráficos/Gráficos con TikZ|Gráficos con {{Verb|TikZ}}]]
# [[Manual de LaTeX/Inclusión de gráficos/Gráficos con PSTricks|Gráficos con PSTricks]]
# [[Manual de LaTeX/Inclusión de gráficos/El paquete XY-Pic|El paquete XY-Pic]]
# [[Manual de LaTeX/Inclusión de gráficos/Creación de graficos en 3D|Creación de graficos en 3D]]
[[Manual de LaTeX/Listados de código|Capítulo 7. Listados de código]]
# [[Manual de LaTeX/Listados de código/Listados con listings|Listados con {{Verb|listings}}]]
# [[Manual de LaTeX/Listados de código/Listados con minted|Listados con {{Verb|minted}}]]
[[Manual de LaTeX/Otros|Capítulo 8. Otros]]
# [[Manual de LaTeX/Otros/Paquetes para componer documentos sobre el juego del Ajedrez|Composición de documentos sobre el juego del Ajedrez]]
# [[Manual de LaTeX/Otros/Exportar a otros formatos|Exportar a otros formatos]]
# [[Manual de LaTeX/Otros/Edición de textos en tengwar|Edición de texto en sistema de escritura tengwar (élfico)]]
== Apéndices ==
# [[/¿Qué necesito para empezar con LaTeX?|¿Qué necesito para empezar con LaTeX?]]
# [[/¿Cómo se procesa un documento LaTeX?|¿Cómo se procesa un documento LaTeX?]]
# [[/Introducción a la creación de proyectos en LaTeX|Introducción a la creación de proyectos en {{LaTeX}}]]
# [[/Primeras aproximaciones con ejemplos sencillos|Primeras aproximaciones con ejemplos sencillos]]
# [[/Proyectos colaborativos en LaTeX|Proyectos colaborativos en {{LaTeX}}]]
# [[/Exportar a otros formatos|Exportar a otros formatos]]
# [[/Documentos estructurados|Documentos estructurados]]
# [[/Instrucciones y entornos|Instrucciones y entornos]]
# [[/Tipos de letra|Tipos de letra]]
# [[/Beamer|Beamer]]
== Enlaces sobre LaTeX ==
{{buscar en libro}}
{{-wikipedia|TeX}}
{{-wikipedia|LaTeX}}
* [http://www.cervantex.es/ CervanTeX, grupo de usuarios de TeX hispanohablantes]
* [http://www.tex-br.org/index.php/P%C3%A1gina_principal Amigos Brasileiros,el wiki LaTeX brasileiro]
* [http://navarroj.com/latex/ LaTeX Fácil]
== Autores y licencia ==
Los autores son los contribuyentes de Wikilibros. Para saber más sobre ellos revisa el [//es.wikibooks.org/w/index.php?title=Manual_de_LaTeX&action=history historial] de este libro.
{{Estantes|Lenguajes de programación}}
[[bn:লাটেক]]
[[de:LaTeX-Kompendium]]
[[en:LaTeX]]
[[fr:LaTeX]]
[[he:לאטך]]
[[hy:ԼաՏեԽ]]
[[ja:TeX/LaTeX入門]]
[[nl:LaTeX]]
[[pl:LaTeX]]
[[pt:Latex]]
[[ro:LaTeX]]
[[ru:LaTeX]]
[[tr:LaTeX]]
[[zh:LaTeX]]
c515aakkyyvx2naubcs0nwktqyzbekk
Manual de LaTeX/Introducción/Instalación
0
2425
436548
351975
2026-10-15T07:48:39Z
Antimundo
74354
Categorizar usando AutoCat
436548
wikitext
text/x-wiki
A menos que se recurra un sistema en línea, el primer paso para usar LaTeX es instalarlo en el sistema. Al ser código abierto no hay un único instalador, incluso en un determinado sistema. A cada uno de los instaladores existentes —que difieren en detalles sobre lo que se incluye y la forma como se gestiona y se actualiza— se lo llama ''distribución''. La mayoría de las distribuciones actuales instalan todo lo necesario para trabajar con LaTeX, incluyendo entornos de edición.
# [[Manual de LaTeX/Introducción/Instalación/Instalación en Linux|Instalación en Linux]]
# [[Manual de LaTeX/Introducción/Instalación/Instalación en OS X|Instalación en OS X]]
# [[Manual de LaTeX/Introducción/Instalación/Instalación en Windows|Instalación en Windows]]
Alternativamente y como ya se ha señalado, puede recurrirse a un editor en línea, como:
* [https://www.overleaf.com/ Overleaf]
* [https://es.sharelatex.com/ ShareLaTeX]
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Instalación
|anterior=Introducción/La escritura en LaTeX
|siguiente=Introducción/Programas_complementarios
}}
{{AutoCat}}
7jl7iv8yekb8ged3h5aey7rlt0j55om
Análisis de Redes Sociales
0
14252
436531
355650
2026-10-15T07:40:55Z
Antimundo
74354
Aviso de borrado
436531
wikitext
text/x-wiki
{{Aviso de borrado|Este libro además de ser un esbozo al tener muchísimo contenido incompleto y estar abandonado por sus autores originales, incumple claramente [[WL:NOES]] al tratarse de una investigación original.}}
{{Propuesta}}
== Presentación==
Una red social ([[:m:w:en:Social_network|social network]]) es una estructura social compuesta por '''nodos''' (''nodes'') y '''relaciones''' (''ties'') entre esos nodos. Mejor dicho, es una estructura social (o un aspecto de una estructura social) que puede modelarse mediante nodos y relaciones. Así, cuando se hace análisis de redes sociales, lo que se está llevando a cabo es una abstracción o modelo de un fenómeno social en el que el elemento fundamental son las relaciones entre los participantes.
Los nodos son generalmente individuos u organizaciones de individuos. Las relaciones son de diferentes tipos y dependen del tipo de red que estemos estudiando, desde relaciones interpersonales como las relaciones de amistad, hasta relaciones formales entre empresas, como las coincidencias de miembros en consejos de administración.
El '''Análisis de Redes Sociales''' es la disciplina que trata del estudio, medida e investigación de redes sociales tal y como las hemos definido. No es más que una aproximación metodológica que enfatiza el estudio de las relaciones entre personas, organizaciones, países o cosas. Nace a partir de las aportaciones de la sociología, la psicología, la antropología y las matemáticas.
== Contenidos ==
* [[Análisis de Redes Sociales/Centralidad y prestigio]]
* [[Análisis de Redes Sociales/Grafos]]
* [[Análisis de Redes Sociales/Apendices/Conceptos de Pajek]]
* [[Análisis de Redes Sociales/Apendices/Redes Ilustrativas]]
== Software utilizado ==
Esta obra se basa en el uso del software abierto [http://vlado.fmf.uni-lj.si/pub/networks/pajek/ Pajek].
== Autores ==
[http://www.cc.uah.es/msicilia Miguel-Angel Sicilia] y [http://www.cc.uah.es/ssalonso Salvador Sánchez-Alonso]
ambos miembros del grupo de investigación [http://ieuah.wordpress.com/ IE] de la [http://www.uah.es/ Universidad de Alcalá]
[[Categoría:Análisis de redes sociales]]
tox2rc9902jxamc1wo7w1jlbs50tc0u
Plantilla:LaTeX
10
15109
436534
220946
2026-10-15T07:45:49Z
Antimundo
74354
Categorizar usando AutoCat
436534
wikitext
text/x-wiki
<math>\mathbf{L\!\!^{{}_{\scriptstyle A}} \!\!\!\!\!\;\; T\!_{\displaystyle E} \! X}</math>{{#ifeq: {{{1}}}|2e| <math>2_\epsilon</math>}}<noinclude>{{AutoCat}}</noinclude>
s2wymgeinijvl344j9nbpm85psjxxaj
436535
436534
2026-10-15T07:46:26Z
Antimundo
74354
436535
wikitext
text/x-wiki
<math>\mathbf{L\!\!^{{}_{\scriptstyle A}} \!\!\!\!\!\;\; T\!_{\displaystyle E} \! X}</math>{{#ifeq: {{{1}}}|2e| <math>2_\epsilon</math>}}<noinclude>[[Categoría:Estante:LaTeX]]</noinclude>
g750u61pr9y3jbvus13olptb37j14mn
436536
436535
2026-10-15T07:46:39Z
Antimundo
74354
436536
wikitext
text/x-wiki
Categorizar usando AutoCat<math>\mathbf{L\!\!^{{}_{\scriptstyle A}} \!\!\!\!\!\;\; T\!_{\displaystyle E} \! X}</math>{{#ifeq: {{{1}}}|2e| <math>2_\epsilon</math>}}<noinclude>[[Categoría:Libro:LaTeX]]</noinclude>
rs8qo9xtxalj67rk0x2hv8rlusjghrl
Manual de LaTeX/Introducción
0
15110
436547
339406
2026-10-15T07:48:33Z
Antimundo
74354
Categorizar usando AutoCat
436547
wikitext
text/x-wiki
En este capítulo estudiaremos algunos detalles fundamentales que el lector debe conocer sobre {{LaTeX}}: Su instalación en diversas plataformas y la compilación de documentos escritos en {{LaTeX}}. También mencionaremos algunos programas útiles que te ayudarán tanto en la escritura de tus archivos {{LaTeX}} como en la compilación de los mismos. Algunos de los programas de los que hablaremos te ayudarán también a crear y convertir gráficos y dejarlos listos para ser incluidos en tu documento.
# [[Manual de LaTeX/Introducción/Introducción a LaTeX|Introducción a {{LaTeX}}]]
# [[Manual de LaTeX/Introducción/La escritura en LaTeX|La escritura en {{LaTeX}}]]
# [[Manual de LaTeX/Introducción/Instalación|Instalación]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en Linux|Instalación en Linux]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en OS X|Instalación en OS X]]
## [[Manual de LaTeX/Introducción/Instalación/Instalación en Windows|Instalación en Windows]]
# [[Manual de LaTeX/Introducción/Programas complementarios|Programas complementarios]]
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Introducción
|siguiente=Introducción/La escritura en LaTeX
}}
{{AutoCat}}
044sclgkc1fnqeihpn1h7bj33gj2dyc
Manual de LaTeX/Introducción/Introducción a LaTeX
0
15112
436552
413786
2026-10-15T07:49:34Z
Antimundo
74354
Categorizar usando AutoCat
436552
wikitext
text/x-wiki
Este artículo está destinado principalmente a comparar TeX con los procesadores de texto, así como para analizar las ventajas e inconvenientes, pero no es esencial y puede omitirse.
== Introducción ==
En primer lugar hay que señalar que {{LaTeX}} no es un procesador de textos, como lo es ''Kword'', ''Abiword'' o ''Writter'' de la suite ofimática Openoffice.org. Sino más bien es un lenguaje de programación que en vez de presentarnos en pantalla una interfaz gráfica produce textos para ser leídos o impresos, de una gran calidad tipográfica. Para hacernos una idea de lo que puede ser {{LaTeX}} pensemos que éste es algo similar a lo que sucede con el código fuente de las páginas web. La página es escrita según unas reglas que entiende el navegador y que nos permite visualizar dichas páginas de un modo intuitivo. Puede comprobarse esto fácilmente pidiéndole al navegador web que muestre el código fuente de esta página. Como se ve lo escrito y lo visualizado no coinciden. {{LaTeX}} procede de modo similar. Lo que se escribe no es lo que se ve en pantalla. ¿Puede esto tener alguna ventaja práctica? ¿Hay alguna razón para abandonar los procesadores de texto que usamos todos los días para realizar nuestros trabajos? Lo que sigue intentará mostrar bajo qué circunstancias {{LaTeX}} puede representar una ventaja frente a otros modos más amigables para trabajar los documentos escritos.
Imagine usted lo siguiente: Tiene que escribir un largo trabajo de investigación, todo lleno de fórmulas matemáticas, de citas a pie de página y muchos libros de referencia. Imagine que tiene que editar un enorme documento de casi mil páginas y que está dividido en 70 pequeños archivos. ¿Cómo hacer un índice a partir de 70 archivos? ¿Cómo evitar que haya cambios de fuentes o de formato indeseables y que todas las páginas tengan los mismos márgenes? ¿Cómo proceder para que el programa editor no haga cosas extrañas e irreversibles? ¿Cómo saber si todas las comillas que he abierto han sido cerradas? Estos ejemplos no son casos aislados, ni hipotéticos, sino que se refieren al uso cotidiano de los procesadores de textos en entornos académicos y universitarios. Para estos usos los procesadores de textos pensados para las oficinas se quedan un tanto cortos en cuanto al respeto de las más elementales normas tipográficas. Ahora bien, como cada uno de nosotros no es siempre un profesional de la tipografía es conveniente que alguien haga por nosotros dicho trabajo tipográfico. Aquí es donde hace su aparición el entorno {{LaTeX}}.
Para hacer más comprensible esta utilización sigamos con los actos de imaginación. Imagine ahora que dispone usted de un programa al cual sólo hay que darle las órdenes y éste las realiza por usted. Por ejemplo, le dice usted que esto que escribe es un libro o una obra de teatro o un artículo de astronomía o una carta. Como verá cada una de estas obras tiene una estructura propia que {{LaTeX}} de antemano sabe y maneja según plantillas que respetan la cabalidad las normas tipográficas. Imagine también que dentro de un libro usted le señala a {{LaTeX}} que éste es el título, éste el autor y la fecha. Con estos elementos {{LaTeX}} compondrá la portada. Además, puedo indicarle que esto es un capítulo (no sé si acabará siendo el primero o el vigésimoquinto), aquí una sección (no sé cuál es su número exacto), esto una nota al margen que siempre debe estar a la altura de tal línea (aunque introduzca cientos de líneas más después), aquí una nota al pie; quiero además que en el encabezado de cada página vaya el número del capítulo y el nombre de la sección, etc. El usuario da las órdenes y {{LaTeX}} se encargará por usted de formatear el documento según las instrucciones que le ha dado. El usuario sólo se dedica a escribir el texto, de la maquetación se encarga {{LaTeX}}. Los resultados finales de esta maquetación son en la mayoría de los casos muy superiores a los que el usuario obtiene manualmente con procesadores de texto WYSIWYG<ref name=WYSIWYG/>.
En general los usuarios que utilizan los procesadores de textos lo hacen como si fuesen máquinas de escribir sofisticadas. Sin embargo, un texto es un producto que debe respetar un mínimo de normas para su legibilidad. La belleza estética de un texto no es criterio suficiente para establecer su comprensibilidad, lo que importa más bien es su estructura lógica. Un escrito lógicamente estructurado es mucho más legible que un texto solo estéticamente agradable. En este aspecto el uso de {{LaTeX}} representa para el autor una enorme ventaja, ya que al escribir los textos pensando que hay que estructurarlos en vista de su legibilidad, se logra que lo escrito se le presente al lector lo que se quería decir. Desde este punto de vista {{laTeX}} es un entorno de trabajo casi insuperable por su poder de edición de documentos con alta legibilidad.
Otro ejemplo de como se procede con textos estructurados que no coinciden con lo que usted ve en pantalla o en forma impresa: Imagine usted que ha realizado la traducción de una obra medieval y la ha maquetado a dos columnas. En cada página la primera columna contiene el texto latino y enfrente la traducción castellana sincronizada con la versión original. La traducción consta de unas 600 páginas. Usted termina la traducción del texto, pero le dicen que éste debe ser presentado ahora, no en columnas sino que la página izquierda debe contener el texto original y la página derecha la traducción. Y debe entregarlo maquetado al día siguiente. ¿Qué hacer? ¿Cuántas horas perdidas? ¿Tendrá usted que dejar de dormir para cumplir con los plazos? En esta ocasión {{LaTeX}} muestra todas sus ventajas. Que un texto esté organizado en dos columnas o en páginas enfrentadas no significa ningún problema. La lógica de la traducción es que a cada texto latino corresponda su traducción castellana. Eso se indica en cada párrafo: aquí el texto original y esta es su traducción. Para obtener aquello solicitado lo único que habría que decirle a {{LaTeX}} es que ordene en columnas o en páginas. Para lograr esto solo basta con cambiar una instrucción de tres letras por otra de tres letras. Vale decir, entre dos o tres segundos. {{LaTeX}} es el perfecto sirviente que cumple con las órdenes que le damos. Lo único que hay que aprender es precisamente las órdenes para que {{LaTeX}} las cumpla por nosotros. Además estas instrucciones son las mismas desde hace años. Por lo que no hay que estar siempre aprendiendo nuevos comandos conforme aparezcan nuevas versiones más actualizadas. Lo que aprendí hace diez años sigue tan vigente hoy como dentro de viente años más.
== Qué es {{LaTeX}} exactamente ==
'''{{LaTeX}}''' es un sistema de tipografía que permite crear documentos con un aspecto completamente profesional de una forma sencilla. La idea principal es que el autor se centre en el contenido y no en la forma del documento. Para lograr esto, {{LaTeX}} está provisto de una serie de macros y estilos predefinidos.
Vamos a poner un ejemplo básico: en una herramienta de procesamiento de texto estándar para hacer el título de una sección, la mayoría usa comandos para modificar la forma, por ejemplo, se pone en negrita, subrayado y a tamaño 16. Con {{LaTeX}}, el aspecto del documento es independiente del contenido: el título de la sección se marca con el comando {{Verb|\section}} y {{LaTeX}} se encargará de formatearlo correctamente cuando sea impreso y mostrado según la plantilla de documento que se emplee.
Hay disponible una gran variedad de paquetes para facilitar la representación de fórmulas matemáticas, notación musical, fórmulas químicas, circuitos electrónicos y mucho más. Concretamente, {{LaTeX}} es realmente fantástico escribiendo fórmulas matemáticas, se pueden hacer cosas como <math>\int_{-N}^{N} e^x\, dx \,\!</math> con gran facilidad, incluso si la fórmula es realmente simple, una vez usado, no querrás hacerlo de otra manera.
En otros téminos, {{LaTeX}} es una serie de instrucciones (macros) basado en el sistema de edición de bajo nivel {{TeX}}. En su origen fue especialmente diseñado para la composición de textos científicos, sobre todo para aquellos que deben incluir una gran cantidad de fórmulas matemáticas. Sin embargo, las posibilidades que {{LaTeX}} ofrece hacen de él un programa idóneo para componer textos de cualquier índole, y más aún si estos son muy grandes. De hecho, puede afirmarse que si algo puede ser impreso se puede realizar con la combinación {{LaTeX}} y {{TeX}}.
{{LaTeX}} combina inigualablemente la sencillez de edición, la calidad tipográfica y la facilidad para garantizar una buena estructura y organización del documento, todo esto de manera casi automática. Así, uno no tiene que hacer más que concentrarse en el contenido del documento y en señalar unas cuantas instrucciones para que {{LaTeX}} haga lo que las instrucciones le indiquen: hacer una portada, un índice de contenidos, poner las notas a pie de página, insertar una imagen, etc. Por ejemplo, en lugar de seleccionar manualmente el tipo de fuente que usaremos para el título de una sección, su tamaño y su estilo (y de recordar todo esto para cuando se llegue el momento de iniciar otra sección), en {{LaTeX}} sólo tenemos que indicarle dentro del documento que en un determinado lugar se inicia una sección, así basta con escribir {{Verb|\section{''Nombre de la sección''|f}}, y con ello obtendremos un verdadero título de sección con todo y su numeración, con independencia de las secciones que podamos insertar antes o después de esta instrucción de estructura del texto.
No obstante, lo primero con lo que nos vamos a encontrar es que {{LaTeX}} no es, por sí mismo, uno de esos programas que ofrecen una interfaz de usuario intuitiva, como lo hacen los programas de tipo WYSIWYG, sino que nuestra escritura en {{LaTeX}} consiste en una serie de comandos cuyo efecto no será visible hasta después de una compilación. Desde este punto de vista, {{LaTeX}} es menos "amigable" que otros editores de texto. Sin embargo, no cuesta realmente mucho trabajo aprender a usar {{LaTeX}} e identificarse con él, —menos aún considerando la gran cantidad de documentación que a propósito existe—, y tomando en cuenta los resultados que pueden alcanzarse con este programa, {{LaTeX}} termina siendo, en la mayoría de los casos, la mejor opción. Para que el lector se convenza de esto bastará que siga leyendo este libro, lleno de ejemplos de lo que se puede hacer con {{LaTeX}}.
== Razones para usar {{LaTeX}} ==
Uno se puede preguntar qué ventajas conlleva el uso de {{LaTeX}}:
* No hay que recordar qué estilo se usó para las secciones previas, las subsecciones, los capítulos y demás.
* Si la fuente del título de sección resulta ser demasiado grande no es necesario cambiarla en todo el documento, se puede hacer con una modificación sencilla.
* Al estar el documento marcado con secciones, subsecciones y demás, resulta más sencillo crear tablas de contenido, de hecho, se crean automáticamente.
* Es software libre, se distribuye bajo la [[w:LPPL|Licencia Pública del Proyecto LaTeX (LPPL)]].
* Funciona bien en cualquier máquina sea cual sea su sistema operativo o el procesador. Hay versiones de {{LaTeX}} para casi todos los sistemas y arquitecturas, la mayoría gratuitas.
* Automatiza muchos procedimientos mecánicos como la autonumeración de fórmulas, la generación de listas y la creación de índices de contenido, de tablas, figuras y terminológicos. Entre otras muchas cosas más.
* Permite el uso de bases de datos bibliográficas con [http://www.bibtex.org BibTeX]. Con el consiguiente ahorro de tiempo a la hora de citar textos y hacer listados de publicaciones. Basta con hacer una vez la base (en modo texto) y {{LaTeX}} se encarga de incluir los datos donde corresponde.
* El resultado final es propio de un texto profesional. Y hay plantillas de {{LaTeX}} que cumplen automáticamente con estándares de publicación científica de muchas revistas.
* Es un programa que con el tiempo mejora la calidad de la salida a pantalla o impresora, pero las instrucciones siguen exactamente iguales, por lo que no es necesario estar aprendiendo cada dos por tres a usarlo. En teoría un texto escrito hoy podría ser procesado exactamente igual dentro de cien años.
* El tamaño de los archivos escritos en {{LaTeX}} es mucho más pequeño que los archivos escritos en un procesador común. Además de ser escritos en modo texto, por lo que pueden ser leídos en cualquier editor con independencia de la arquitectura y sistema operativo.
El usuario no necesita ser un profesional de la tipografía para realizar sus documentos. A modo de ejemplo: ¿cuál es el número máximo de letras que puede contener una línea para que el lector no se canse? La gran mayoría lo ignora. Las razones para usar un sistema de procesador de textos visual es su facilidad de uso. Pero, a la hora de realizar textos elaborados como libros, tesis de grado, ponencias, etc. se muestran sus limitaciones. En definitiva un procesador de textos es una enorme máquina de escribir donde el usuario tiene que introducir manualmente todos los formatos. Y, usualmente, el criterio es más bien estético y no tipográfico, es decir, creemos que un texto bello es sinónimo de legible. Pues bien, eso no es correcto, la tipografía es un arte difícil de manejar. Lo mejor en este caso es dejar en manos de un profesional la maquetación de los documentos.
== Referencias ==
{{listaref|refs=
<ref name=WYSIWYG>WYSIWYG significa "What You See Is What You Get", es decir, "Lo que ve es lo que obtiene".</ref>
}}
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Introducción_a_LaTeX
|anterior=Introducción
|siguiente=Introducción/La escritura en LaTeX
}}
{{AutoCat}}
fzvkujq0l240nkuc8tt44vsqxqkwv6j
Manual de LaTeX/Introducción/La escritura en LaTeX
0
15113
436553
328597
2026-10-15T07:49:41Z
Antimundo
74354
Categorizar usando AutoCat
436553
wikitext
text/x-wiki
Una de las características más importantes de LaTeX es que los autores trabajan con archivos de texto. Dado que LaTeX es un lenguaje de marcas, en estos archivos se combinan órdenes y texto. Para editarlos, puede servir cualquier editor, pero lo recomendable es emplear uno que esté adaptado a las necesidades propias de LaTeX.
[[Archivo:Captura de pantalla TeXStudioen.png|right|300px|thumb|TeXstudio es uno de los entornos gráficos disponibles]]
De hecho, actualmente hay entornos para la edición de LaTeX que integran la edición, la generación del documento y la visualización en PDF. Ejemplos son TeXshop, TeXworks, TeXnicCenter, TeXmaker,... Con ellos no son necesarios los pasos siguientes ni el uso de la consola o terminal, como tampoco cuando se emplea un servicio en línea como [https://www.overleaf.com/ Overleaf] o [https://es.sharelatex.com/ ShareLaTeX].
== Uso con un editor independiente ==
Para escribir en {{LaTeX}} es necesario tener un programa para crear ficheros de formato {{Verb|.tex}}, que no es más que un formato de texto de código ASCII. El archivo {{Verb|.tex}} contendrá todas las instrucciones que serán procesadas por {{LaTeX}} para producir un archivo de salida. Por ejemplo, si hemos creado el archivo {{Verb|ejemplo.tex}}, y queremos compilarlo en formato PDF, abrimos una terminal o símbolo del sistema, nos ubicamos en la dirección donde se encuentre nuestro fichero y escribimos
{{Verb|pdflatex ejemplo.tex|c}}
Con esto obtendremos el documento {{Verb|ejemplo.pdf}} creado a partir de todas aquellas instrucciones contenidas en el archivo {{Verb|ejemplo.tex}}
El formato PDF no es el único que podemos producir. A continuación presentamos una lista de algunos otros comandos que producen distintos formatos de salida:
{|
|valign="top" width="75px" | '''latex'''
|Este comando compilará el fichero {{Verb|.tex}} en un DVI. Este formato es el original de compilación de {{LaTeX}}, pero no es muy común ver documentos de este tipo.
|-
|valign="top" | '''pdflatex'''
| Como ya mencionamos, este comando produce un archivo PDF. Este es quizá el formato más recomendable, pues aún cuando es de mayor tamaño que un DVI, es un formato mucho más común y de mejor calidad de visualización. Sin embargo, no podremos incluir imágenes PostScript, aunque podemos usar el comando siguiente y después convertir el resultado en PDF.
|-
|valign="top" | '''dvips'''
|Este comando no procesará un fichero {{Verb|.tex}}, sino que a partir de un fichero {{Verb|.dvi}}, previamente elaborado con el comando {{Verb|latex}}, produce un documento PostScript (de extensión {{Verb|.ps}}). En general, estos documentos son de mayor tamaño. Pueden ser visualizados con, por ejemplo, Ghostview.
|-
|valign="top" | '''ps2pdf'''
|Este comando convierte los archivos {{Verb|.ps}} en archivos {{Verb|.pdf}}. Así es que, si por alguna razón es necesario compilar el fichero {{Verb|.tex}} en {{Verb|.ps}}, simpre es posible obtener al final un archivo {{Verb|.pdf}}.
|}
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/La escritura en LaTeX
|anterior=Introducción/Introducción_a_LaTeX
|siguiente=Introducción/Instalación
}}
{{AutoCat}}
1sxxypohm7wrnz2jyov22z8guu366ma
Manual de LaTeX/Introducción/Instalación/Instalación en Linux
0
15114
436549
416339
2026-10-15T07:48:48Z
Antimundo
74354
Categorizar usando AutoCat
436549
wikitext
text/x-wiki
== Actualizando ''tetex'' o ''texlive'' ==
Para utilizar {{LaTeX}} en GNU/Linux es muy sencillo. Casi todas las distribuciones la traen por defecto. Basta descargar e instalar el paquete {{Verb|tetex}} (proyecto descontinuado) o bien, el más reciente y actualizado {{Verb|texlive}}. Cada distribución en GNU/Linux maneja a su manera el listado y las dependencias de sus paquetes compilados. A modo de ejemplo, en distribuciones basadas en ''Debian'' bastará abrir un terminal e introducir como ''root' la siguiente orden:
{{Verb|sudo apt-get install texlive-latex-extra texlive-fonts-recommended lmodern}}
Otro modo aun más sencillo que deja todo listo para ser usado es instalar un editor de {{LaTeX}} especializado (ver más adelante) con la siguiente orden:
{{Verb|sudo apt-get install lyx}}
En otras distribuciones como ''SuSe'', ''Mandriva'', ''Fedora'' (basadas en paquetes RPM) hay herramientas gráficas en las cuales es posible seleccionar los mismos paquetes para que sean instalados.
Una vez que lo hagas estará todo listo para comenzar con la creación y compilación de archivos {{LaTeX}}. Más aún, en la mayoría de las distribuciones de GNU/Linux {{LaTeX}} es un programa que es instalado por defecto y está esperando a que se haga uso de él.
== Editores de texto ==
Una vez instalado {{LaTeX}} nos encontramos con que este no es un programa con una interfaz gráfica sino que lo que el usuario debe hacer es escribir sus documentos según ciertas reglas que posteriormente {{LaTeX}} convertirá a un documento legible e imprimible.
Para escribir en {{LaTeX}} necesitarás simplemente un editor de texto. Cualquiera es adecuado para ello. Basta con que el editor de código ASCII ofrezca la posibilidad de guardar el archivo con la extensión {{Verb|.tex}}. Además de editores genéricos existen varios editores muy buenos que no sólo te permitirán guardar tu archivo {{Verb|.tex}}, sino que también ofrecen una serie de herramientas útiles para facilitar la composición. En GNU/Linux estos editores podemos agruparlos en dos varientes: Aquellos en los que se ingresa directamente los comandos de {{LaTeX}} y que el programa compila posteriormente, obteniendo diversas salidas: PDF, DVI, PS, HTML, etc. Y un segundo grupo que es capaz de exportar sus archivos a formato {{LaTeX}}.
En el primer grupo encontramos, a modo de ejemplo, los siguientes programas:
* ''Emacs'', muy útil, pues incluye un entorno de edición especial para {{LaTeX}} (y para algunos otros lenguajes) que, entre otras cosas, colorea los comandos para facilitar la visualización de sintaxis. Poderoso editor de textos, aunque, su instalación ocupa bastante espacio en el disco duro. Aunque incluye un modo de LaTeX, el sistema más completo es AUCTEX con RefTeX.
* ''Vim'', similar a emacs en cuanto a coloreado de sintaxis. Posee además un plugin especial para compilar {{LaTeX}}. Su instalación es pequeña y es, además, un muy poderoso editor de textos.
* ''Texmaker'', programa muy cómodo que permite insertar código y compilar mediente una interfaz de botones muy intuitiva. Es liviano y consume pocos recursos. Viene acompañado de herramientas que informan de los errores.
* ''Kile'', editor especializado en {{LaTeX}} del escritorio KDE. Muy intuitivo y programable. Reconoce los comandos y sugiere autocompletación. Viene con herramientas que indican los errores y abren el archivo en el lugar preciso de dicho error para su corrección.
* ''LaTeXila'' es un editor LaTeX para el entorno de escritorio GNOME, se caracteriza por su facilidad de uso. Compila los documentos directamente a PDF o PostScript con un botón integrado al programa. Tiene la función de auto completado. Indica los errores que se presenten en el archivo y hace fácil encontrarlos. Permite la rápida inserción de símbolos matemáticos, científicos y caracteres griegos, es liviano en cuando a consumo de recursos del ordenador.
En el segundo grupo, exportadores a formato {{LaTeX}} tenemos a su vez dos varientes. Procesadores de textos que pueden exportar desde sus propios formatos a {{LaTeX}}. Y procesadores especializados en {{LaTeX}} que proporcionan una cómoda interfaz gráfica.
* Procesadores que exportan a {{LaTeX}}:
** ''OpenOffice.org'' es capaz de exportar sus archivos (''odt'' 0 ''doc'') a {{LaTeX}}, a partir de los cuales es posible la compilación del archivo {{Verb|.tex}}. Además, este programa está disponible en español, por lo que la edición resulta aún más fácil. OpenOffice.org integra un editor de ecuaciones, y si con el insertas una fórmula matemática, ésta será convertida en los comandos de {{LaTeX}} respectivos para producir la fórmula en tu documento {{Verb|.tex}}. OpenOffice.org, es software gratuito. Hay que tener presente que actualmente el código {{LaTeX}} que genera no es muy perfecto.
** ''Abiword'', procesador de textos del escritorio GNOME. Exporta sus archivos a {{LaTeX}}, aunque su exportación no está muy de acuerdo con un archivo escrito directamente en {{LaTeX}}, pues, al igual que Openoffice.org intenta reproducir el formato original mediante comandos. Lo que no es muy propio de {{LaTeX}}, en el que se intenta más bien escribir textos lógicamente estructurados.
** ''Kword'', procesador de textos del escritorio KDE y parte de la suite ofimática Koffice. Realiza más o menos lo mismo que Abiword y Openoffice.org.
* Respecto del segundo grupo contamos en GNU/Linux con los siguientes programas:
** ''LyX'', este programa sostiene que es del tipo WYSIWYM (lo que vez es lo que quieres decir). Para aquellos que deseen contar con un editor de textos de estilo más "familiar", pueden pensar en utilizar LyX, un editor de textos que emplea {{LaTeX}} para la creación de sus textos, todo en un ambiente muy parecido a WYSIWYG, salvo que lo que ve en la pantalla no es el documento compilado. Para compilar y visualizar basta apretar un botón. Así, si alguien siente que con {{LaTeX}} se trabaja un poco a ciegas, este programa le permitirá cambiar la situación al mostrarle gráficamente todo lo que va haciendo en su documento, sin necesidad de compilar el texto y esperar hasta entonces para ver los resultados.
** ''Texmacs'', es un programa basado en ''emacs'' con un entorno casi WYSYGYG para {{LaTeX}}.
Como se señala estos programas harán que el trabajo resulte más sencillo e interesante, y ayudarán a ganar gusto por {{LaTeX}}. Los programas que exportan a {{LaTeX}} le permiten al usuario obtener desde archivos ''odt'' o ''doc'' el código fuente para {{LaTeX}} y desde estos archivos ir aprendiendo cual es la lógica interna de este modo de edición.
Es interesante señalar que una vez que se aprende a utilizar {{LaTeX}} se hace muy difícil utilizar algún otro programa para componer tus textos con contenido matemático (o de cualquier otro tipo).
El uso de uno u otro de los programas antes mencionados dependerá de los gustos del usuario. Sin embargo, es recomendable iniciarse con algunos programas más intuitivos como ''LyX'' y luego pasar a la edición pura en ''texmaker'' o ''kile''.
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Instalación/Instalación en GNU/Linux
|anterior=Introducción/Instalación
|siguiente=Introducción/Programas_complementarios
}}
{{AutoCat}}
mr30b27w0kwxarxp3pphq3br9g6i5un
Manual de LaTeX/Introducción/Instalación/Instalación en Windows
0
15116
436551
328600
2026-10-15T07:49:27Z
Antimundo
74354
Categorizar usando AutoCat
436551
wikitext
text/x-wiki
Para instalar LaTeX en Windows hay dos opciones básicas: [https://miktex.org/download MikTeX] y [https://www.tug.org/texlive/acquire-netinstall.html TeXLive]. La primera es más fácil de instalar y mantener, aunque la segunda es mucho más completa y por lo general más actualizada.
== Repositorios ==
Para instalarlo se debe bajar una aplicación de instalación que contiene los paquetes y programas básicos de {{LaTeX}}. Al correr esta aplicación, se ejecuta un asistente que guiará al usuario durante la instalación de MikTeX. Entre otras cosas, se solicita la confirmación de la dirección donde se guardarán los paquetes de {{LaTeX}}. Por defecto, el asistente creará una carpeta llamada "texmf", en la unidad de disco local, a menos que se indique lo contrario. Es conveniente que se permita la creación de la carpeta tal y como lo propone el asistente para evitar problemas más adelante. Posteriormente, mediante un programa que se instalará junto con MikTeX, el '''MikTeX Package Manager''', se podrán descargar los paquetes de {{LaTeX}} que se necesiten. Existen algunos paquetes menos estándares que no se descargan de forma automática con MikTeX Package Manager, sino que es necesario instalarlos manualmente desde páginas específicas dedicados a {{LaTeX}}.
== Editores ==
Para editar ficheros {{Verb|.tex}} se pueden emplear editores como [http://www.xm1math.net/texmaker/download.html TeXmaker], [http://www.texniccenter.org/download/ TeXnicCenter] u otros similares. Estos cuentan con una gran cantidad de herramientas, dentro de las cuales la más útil es quizá la compilación misma del documento, implementando una serie de instrucciones para compilar el archivo en distintos formatos de salida, como lo son el PDF, el DVI y el PostScript. De este modo no será necesario abrir la consola (o Símbolo del sistema o Command Prompt) para realizar la compilación. Por supuesto, para que esto funcione, es necesario indicar previamente al editor dónde se encuentra el programa de {{LaTeX}} que debe ejecutar para compilar el archivo {{Verb|.tex}}. Esto se hace la primera vez que se inicia el editor, y si se ha permitido que MikTeX se instalara en la carpeta "texmf", no será necesario realizar ningún ajuste extra, ya que el editor asume que los paquetes y programas de {{LaTeX}} se instalaron en la carpeta por defecto y sólo será necesario confirmar las rutas que se señalan.
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Instalación/Instalación en Windows
|anterior=Introducción/Instalación
|siguiente=Introducción/Programas_complementarios
}}
{{AutoCat}}
aru9dhtyuktnajbfd7jrqt4ztp2uu52
Manual de LaTeX/Introducción/Programas complementarios
0
15117
436554
354781
2026-10-15T07:49:47Z
Antimundo
74354
Categorizar usando AutoCat
436554
wikitext
text/x-wiki
El sistema de TeX sigue el principio de no ofrecer una aplicación monolítica cerrada. En lugar de ello, prefiere ofrecer un conjunto de programas especializados de modo que se pueda optar por uno u otro de las diferentes posibilidades según las necesidades concretas de un determinado flujo documental. Entre los programas que la mayoría de las distribuciones ofrecen están bibtex y makeindex, para gestión de bibliografías e índices alfabéticos; algunas incluyen alternativas que pueden resultar más flexibles, como biber y xindy, respectivamente.
== «Motores» ==
Además de los programas complementarios, hay que tener en cuenta que el propio programa que genera los documentos tiene variantes, que desarrollan el primitivo.
; tex
: Sin más, es el programa original. El documento generado tiene el formato dvi, que es especíifico de TeX y necesita un visualizador especial. Por ello, lo normal es que se convierta posteriormente a otros formatos más generales, como PostScript (también de uso limitado) y PDF (que, por el contrario, es universal).
; pdftex
: Es un programa basado en el anteriores que genera directamente archivos PDF. Añade, además, nuevas funciones.
; XeTeX
: También está basado en tex, aunque añade algunas funciones de pdftex. Su propósito principal es trabajar con Unicode y con las fuentes tipográficas instaladas en el sistema.
; LuaTeX
: Esta basado en pdftex y, según sus autores, será su sucesor. No solo trabaja con Unicode y las fuentes instaladas en el sistema, sino que incorpora la posiblidad de extender sus funciones con el lenguaje de programación Lua.
Son estables tex y pdftex. Tanto XeTeX como LuaTeX son bastante estables, aunque no tanto como los anteriores (ambos siguen en desarrollo activo, mientras que pdftex y, sobre todo, tex, se consideran básicamente cerrados con el fin de no introducir posibles incompatibilidades). Este manual presupone que se emplea pdftex, excepto si se indica lo contrario.
== Gráficos ==
Resulta que, al escribir libros con contenido matemático, se nos presenta frecuentemente la necesidad de insertar gráficos, algunos de ellos previamente creados, y otros que aún no sabemos como crear para después incluirlos en nuestro documento. Por ello, conviene, sin entrar en detalles de su uso (esto lo haremos en un capítulo especialmente dedicado a la inserción de gráficos en {{LaTeX}}), mencionar algunos programas, todos gratuitos, con los cuales puedes convertir y crear tus gráficos para después utilizarlos en {{LaTeX}}.
Para la conversión de gráficos a distintos formatos una opción muy popular es ''[https://www.imagemagick.org/script/index.php ImageMagick]''. Este programa convierte gráficos a muy distintos formatos, además de que, en el proceso, puede hacer distintas transformaciones en la imagen misma. Este programa se trabaja mediante comandos en una terminal o símbolo del sistema. Si el lector prefiere un programa más visual, hay diversas opciones, como ''[http://gimp.es/descargar/ Gimp]''.
Para crear gráficos, es recomendable usar los paquetes que incluye el propio {{LaTeX}}, como {{Verb|PSTricks}} y sus derivados ({{Verb|pst-3dplot}}, {{Verb|pst-labo}}, {{Verb|pst-func}}, etc.) o {{Verb|TikZ}}, dado que de esta forma se dispondrá de más posibilidades de realizar las tareas que se requieren para adaptar los gráficos al documento.
Además, existen programas que funcionan casi como un procesador de textos, pero que son capaces de transformar los textos a formato {{LaTeX}}. Algunos proyectos interesantes son los editores [http://www.xm1math.net/texmaker/download.html TeXmaker] [http://www.lyx.org LyX], que facilitan la escritura de documentos en LaTeX y es un modo más simple de iniciarse en la escritura de documentos estructurados en {{LaTeX}}.
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Programas_complementarios
|anterior=Introducción/Instalación
|siguiente=La estructura de un documento en LaTeX
}}
{{AutoCat}}
iyf998mng3vg9q9r483tubiocsp9qyk
Manual de LaTeX/La estructura de un documento en LaTeX/Preámbulo/Clases de documento
0
15119
436559
385202
2026-10-15T07:50:30Z
Antimundo
74354
Categorizar usando AutoCat
436559
wikitext
text/x-wiki
{{Navegar índice
|libro=Manual de LaTeX
|actual=Clases de documento
|anterior=La estructura de un documento en LaTeX/Preámbulo
|siguiente=La estructura de un documento en LaTeX/Preámbulo/Paquetes comunes|Paquetes comunes
}}
Como mencionábamos, existen diferentes estilos que podemos darle a nuestro documento, y la selección de uno u otro dependerá de qué es lo que necesitamos hacer. Si queremos escribir un documento corto, podemos utilizar la clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight>. En términos generales, esta clase de documento nos permite dividir el documento en secciones, subsecciones, párrafos y subpárrafos.
A continuación una lista de algunas clases típicas de documento:
{|
|valign="top" width="75px" | '''article'''
|Para artículos académicos y otros documentos cortos que no es necesario dividir en capítulos, sino que bastan las secciones y subsecciones y sus párrafos y subpárrafos.
|-
|valign="top" | '''book'''
|Para libros y otros documentos más largos que deben incluir capítulos, prólogo, apéndices o incluso partes.
|-
|valign="top" | '''report'''
|Para informes técnicos. Es similar a la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight>.
|-
|valign="top" | '''memoir'''
|Una clase todoterreno con un buen número de funciones adicionales integradas.
|-
|valign="top" | '''beamer'''
|Otra clase para presentaciones mediante diapositivas.
|}
Las clases <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">report</syntaxhighlight> son muy similares, y ambas sirven para documentos grandes, como lo son, naturalmente, los libros y los reportes, entre otros trabajos. Sin embargo, existen ligeras diferencias. Por ejemplo, la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> hace que los capítulos empiecen siempre en una página impar, de modo que si un capítulo anterior termina en una página impar, la página (par) siguiente quedará en blanco y el capítulo nuevo comenzará después de ella. Esto, en cambio, no sucede con la clase <syntaxhighlight lang="latex" enclose="none">report</syntaxhighlight>, así es que un capítulo simplemente empieza en una página nueva, sea par o impar. Por supuesto, estas opciones pueden ser fácilmente modificadas. Todas las clases de la lista anterior admiten opciones adicionales. Por ello, la sintaxis general para indicar una clase de documento es la siguiente:
<center><syntaxhighlight lang="latex">\documentclass[''opción 1, opción 2, ...'']{''clase de documento''}</syntaxhighlight></center>
Las opciones que podemos dar son:
{|{{Tablabonita}}
|valign="top" width="75px"| '''a4paper, letterpaper, ...'''
|valign="top" |Con esta opción indicamos que el tamaño del papel debe de ser <syntaxhighlight lang="latex" enclose="none">a4paper</syntaxhighlight> (tamaño a4), <syntaxhighlight lang="latex" enclose="none">letterpaper</syntaxhighlight> (tamaño carta), ... Otras opciones que determinan distintos tamaños de página son:
* <syntaxhighlight lang="latex" enclose="none">a5paper</syntaxhighlight> (210 mm <math>\times</math> 148 mm)
* <syntaxhighlight lang="latex" enclose="none">b5paper</syntaxhighlight> (250 mm <math>\times</math> 176 mm)
* <syntaxhighlight lang="latex" enclose="none">legalpaper</syntaxhighlight> (14 in <math>\times</math> 8.5 in)
* <syntaxhighlight lang="latex" enclose="none">executivepaper</syntaxhighlight> (10.5 in <math>\times</math> 7.25 in)
El valor por defecto es letterpaper, de Estados Unidos y México. En los documentos de otros países puede ser necesaria la opción a4paper.
|-
|valign="top" | '''landscape'''
|valign="top" | Apaisado. Pone la página de forma horizontal.
|-
|valign="top" | '''10pt, 11pt, 12pt'''
|valign="top" |Definen el tamaño de la fuente principal del texto.
|-
|valign="top" | '''oneside, twoside'''
|valign="top" |Indican si el documento debe estar adaptado a impresión por un sólo lado de la página o por ambos lados de ella.
|-
|valign="top" | '''titlepage, notitlepage'''
|valign="top" |Determinan si el documento debe o no incluir una página de título, i.e. si va a incluir o no una portada.
|-
|valign="top" | '''openright, openany'''
|valign="top" |<syntaxhighlight lang="latex" enclose="none">openright</syntaxhighlight> obliga a los capítulos a iniciar siempre sólo en páginas impares, mientras que con la opción <syntaxhighlight lang="latex" enclose="none">openany</syntaxhighlight> permitimos que los capítulos se inicien en cualquier página.
|-
|valign="top" | '''onecolumn, twocolumn'''
|valign="top" |Definen si el documento se va a escribir en una sola columna o a doble columna.
|-
|valign="top" | '''fleqn'''
|valign="top" |Esta opción hace que las ecuaciones queden alineadas por la izquierda en lugar de que sean centradas (como sucede por defecto).
|-
|valign="top" | '''leqno'''
|valign="top" |Con esta opción hacemos que el número de las ecuaciones quede alineado por la izquierda en lugar de por la derecha (como sucede por defecto).
|-
|valign="top" | '''draft, final'''
| La opción <syntaxhighlight lang="latex" enclose="none">draft</syntaxhighlight> se usa si queremos que la compilación del documento se haga a modo de "borrador". Con <syntaxhighlight lang="latex" enclose="none">draft</syntaxhighlight> haremos que las líneas que sean demasiado largas queden marcadas mediante cajas negras. La opción <syntaxhighlight lang="latex" enclose="none">final</syntaxhighlight> producirá simplemente que el documento se compile de manera normal.
|}
Cuando no especificamos opciones para una clase de documento, se cargan las opciones por defecto de la clase que estemos utilizando. Por ejemplo, si escribimos
<center><syntaxhighlight lang="latex">\documentclass[letterpaper,10pt,twoside,onecolumn,final,openright]{book}</syntaxhighlight></center>
sería lo mismo que si escribiéramos simplemente
<center><syntaxhighlight lang="latex">\documentclass{book}</syntaxhighlight></center>
pues la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> tiene como opciones por defecto <syntaxhighlight lang="latex" enclose="none">letterpaper,10pt,twoside,onecolumn,final,openright</syntaxhighlight>. Además, la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> producirá automáticamente una página para el título del documento. Con la opción <syntaxhighlight lang="latex" enclose="none">notitlepage</syntaxhighlight> haremos que esto no suceda así, de manera que el título del documento no quedará en una página aparte.
La clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight> carga automáticamente las opciones <syntaxhighlight lang="latex" enclose="none">letterpaper,10pt,oneside,onecolumn,final</syntaxhighlight>. Puesto que en la clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight> no existen capítulos, las opciones <syntaxhighlight lang="latex" enclose="none">openright</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">openany</syntaxhighlight> no están permitidas.
Las opciones por defecto de la clase <syntaxhighlight lang="latex" enclose="none">report</syntaxhighlight> son <syntaxhighlight lang="latex" enclose="none">letterpaper,10pt,oneside,final,openany</syntaxhighlight>.
== Diseño del documento ==
Tanto los márgenes como el tamaño del papel se pueden cambiar a los valores que se deseen con el paquete geometry. Un ejemplo simple, que ajusta todos los márgenes a 1 cm en una hoja DIN A5, es:
\usepackage[a5paper,margin=1cm]{geometry}
Un paquete alternativo es zwpagelayout, con menos opciones, pero que ajusta internamente los parámetros necesarios en un PDF (y que tiene otras funciones como marcas de corte, por ejemplo).
{{AutoCat}}
54cdc5p5tnv6ysjw6x7i9ytemtexzps
Manual de LaTeX/La estructura de un documento en LaTeX
0
15120
436555
404478
2026-10-15T07:49:53Z
Antimundo
74354
Categorizar usando AutoCat
436555
wikitext
text/x-wiki
Como ya se ha explicado cómo se compila un documento en {{LaTeX}}, pero no se ha hablado aún de cómo escribir el documento a compilar. En este capítulo se analiza la estructura básica de un documento, y en el siguiente capítulo se expondrán los conceptos básicos sobre la escritura de texto en {{LaTeX}}.
== La estructura ==
La estructura de un documento en {{LaTeX}} se divide en dos grandes partes: el preámbulo y el cuerpo del texto.
El siguiente ejemplo muestra un documento mínimo apropiado para el español:
<syntaxhighlight lang="latex">
\documentclass[spanish]{article}
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[utf8]{inputenc} % Puede depender del sistema o editor
\begin{document}
Aquí iría el texto del documento en sí.
\end{document}
</syntaxhighlight>
=== Preámbulo ===
En el ''preámbulo'' se escriben las instrucciones fundamentales que indican a {{LaTeX}} qué [[Manual de LaTeX/La estructura de un documento en LaTeX/Preámbulo/Clases de documento|clase de documento]] se va a escribir y qué características va a tener éste, así como también las que indican a {{LaTeX}} qué [[Manual de LaTeX/La estructura de un documento en LaTeX/Preámbulo/Paquetes comunes|paquetes]] se deben cargar. El preámbulo siempre empezará con la instrucción:
<syntaxhighlight lang="latex">
\documentclass[<opciones>]{<plantilla_documento>}
</syntaxhighlight >
Para definir la plantilla que se va a emplear en el documento, como por ejemplo {{Verb|article}} o {{Verb|report}}, que determinan diferentes estilos. En general, los argumentos que toma este comando son las llamadas ''clases'' de documento, y pueden aceptar diferentes opciones. Por ejemplo, la instrucción:
<syntaxhighlight lang="latex">
\documentclass[12pt, letterpaper]{book}
</syntaxhighlight>
Declara que el documento es un libro, con el tamaño de letra configurado a 12 puntos y utilizando papel tamaño carta. En vez de {{Verb|letterpaper}}, se pueden usar otros tamaños de papel, como lo es A4 ({{Verb|a4paper}}).
====Paquetes====
Se llama paquete a una extensión del sistema básico que añade nuevas funciones. Hay, literalmente, cientos de paquetes con muy diversas funciones: inserción de imágenes ({{Verb|graphicx}}), paquetes gráficos ({{Verb|TikZ}}), internacionalización ({{Verb|babel}}, {{Verb|polyglossia}}), color ({{Verb|xcolor}}), música, ajedrez, ediciones críticas, secuencias de amninoácidos, etc. Todos estos paquetes deberán ser declarados con:
<syntaxhighlight lang="latex">
\usepackage[<opciones>]{<paquete>}
</syntaxhighlight>
Donde entre los corchetes estará el nombre del paquete a usar, por ejemplo:
<syntaxhighlight lang="latex">
\usepackage{amssymb}
</syntaxhighlight>
Para cargar el paquete {{Verb|amssymb}}, que proporciona símbolos matemáticos de la American Mathematical Society. Si una clase de documento o paquete que queremos cargar ofrece opciones y nosotros no especificamos la que queremos, se cargarán las opciones por defecto.
=== Cuerpo ===
El cuerpo del documento consiste en prácticamente todo lo que aparecerá en nuestra compilación. Es aquí, pues, donde escribiremos el texto verdadero.
Comienza con la instrucción
<syntaxhighlight lang="latex">
\begin{document}
</syntaxhighlight>
y termina con:
<syntaxhighlight lang="latex">
\end{document}
</syntaxhighlight>
Todo lo que se escriba con posterioridad a esta instrucción será ignorado por {{LaTeX}} y no se compilará.
Una vez que iniciemos el cuerpo del documento debemos escribir al final de todo lo escrito la instrucción de cierre <syntaxhighlight lang="latex" enclose="none">\end{document}</syntaxhighlight> aunque no hayamos terminado todo el documento, pues de otra manera tendremos un error en el proceso de la compilación y no podremos ir viendo cómo van quedando nuestros avances.
==== Órdenes o macros ====
Hay ciertos caracteres que tienen una función especial, como por ejemplo, el símbolo \, por el que comienzan todas las instrucciones, o las llaves y corchetes, que contienen los datos y opciones de las instrucciones. Por ejemplo, en <code>\title{Un título}</code> hay una orden (en muchos casos también llamadas macros), que es <code>\title</code> y que ajusta el título del documento con el dato (o argumento) que sigue, que es <code>Un título</code> (en este punto no se añade realmente el título al documento, sino que LaTeX tan sólo lee el dato y lo guarda para cuando haga falta).
Otro detalle que hay que destacar es que las órdenes que no van seguidas de algún argumento descartan el o los espacios que le siguen (con la excepción de las órdenes que consisten en un símbolo, como \#, \% o \$). Aunque hay pocas órdenes de este tipo —la mayoría tienen algún dato o consisten en un símbolo— es muy importante tener esto presente por si se diera el caso. La solución en tales casos suele pasar por añadir un «dato» vacío, es decir, un par de llaves.
Finalmente, hay que señalar que algunas órdenes no van seguidas de uno o varios argumentos, sino que operan sobre el texto que le sigue hasta que termina el bloque actual delimitado por llaves. En ocasiones, incluso, hay dos variantes que funcionan de cada uno de estos modos. En caso simple es el siguiente:
\textbf{texto en negrita}
{\bfseries texto en negrita}
Estas dos formas son equivalentes, pero por lo general se prefiere el primer tipo.
Un tipo especial de orden es la que delimita un bloque del documento. Van siempre por pares:
\begin{...}
...
\end{...}
Una estructura así se llama ''entorno'' o ''ambiente'' y la más importante es justamente la que abarca el cuerpo del documento.
==== Principios básicos de la escritura ====
Todo bloque de texto separado del resto con líneas en blanco se considera un párrafo. No es el único caso en que LaTeX considera que hay un párrafo, pero sí es el más importante. En este caso, se lee el texto contenido en ese bloque y LaTeX lo procesa con objeto de encontrar las mejores divisiones de línea, los mejores guiones y el mejor espaciado posible para el párrafo. También se preocupa de encontrar el mejor punto para cambiar de página, así como de cuadrar el resultado en la página. Todo ello, naturalmente, sin necesidad de intervención directa de quien escribe.
El texto de cada párrafo se escribe de modo normal, con algunas salvedades importantes. En primer lugar, un espacio entre palabras vale lo mismo que dos, tres o cientos, siempre que no se deje una línea en blanco. De esta forma se evitan espaciados irregulares que en sistemas WYSIWYG aparecen en ocasiones al teclear por error dos espacios seguidos. En segundo lugar, LaTeX proporciona un buen número de caracteres adicionales a menudo inexistentes en los teclados y que se pueden introducir como órdenes; por ejemplo, \textdagger inserta una cruz (†) en el punto donde aparece. Véamoslo con un ejemplo de documento completo:
<syntaxhighlight lang="latex">
\documentclass[spanish]{article}
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[utf8]{inputenc} % Puede depender del sistema o editor
\title{Un título}
\author{El autor}
\date{5 de marzo del 2015}
\begin{document}
Un breve texto introductorio que servirá como
ejemplo para mostrar qué forma tiene un párrafo.
Hasta ahora solo tenemos uno, que concluimos con
una línea en blanco.
Tras la línea en blanco, tenemos otro párrafo. En
él, además, escribiremos una cruz (\textdagger{}).
Pero interrogaciones, comillas, etc., se escriben
normalmente: ¿de verdad?, «comillas», ¡qué bien!
Los estilos de letra también se introducen con
órdenes, como \textit{cursiva} y \textbf{negrita}.
\end{document}
</syntaxhighlight>
{{navegar
|libro=Manual de LaTeX
|actual=La estructura de un documento en LaTeX
|anterior=Introducción/Programas_complementarios
|siguiente=La estructura de un documento en LaTeX/El preámbulo y el cuerpo del documento
}}
{{AutoCat}}
ejqvccb66h0wc3sr3azbh3z0189vw1v
Manual de LaTeX/Escribiendo texto/Espacios
0
15141
436538
385193
2026-10-15T07:47:06Z
Antimundo
74354
Categorizar usando AutoCat
436538
wikitext
text/x-wiki
En {{LaTeX}}, un espacio en blanco en el texto fuente produce un espacio en blanco en el documento compilado. Más de un espacio en blanco en el texto fuente no producen más que un espacio en blanco en el texto compilado.
Por tanto, si escribimos:
<syntaxhighlight lang="latex">Uno o más espacios equivalen a un solo espacio en blanco</syntaxhighlight>
<syntaxhighlight lang="latex">Uno o más espacios equivalen a un solo espacio en blanco</syntaxhighlight>
obtenemos en ambos casos: Uno o más espacios equivalen a un solo espacio en blanco.
Podemos usar también el comando <syntaxhighlight lang="latex" enclose="none">\hspace{''valor''} </syntaxhighlight> para obtener un espacio horizontal igual al ''valor'' que especifiquemos. Por ejemplo,
<syntaxhighlight lang="latex">Hola\hspace{4cm}adiós</syntaxhighlight>
dejará un espacio horizontal de 4 centímetros entre las palabras "Hola" y "adiós" en el texto compilado.
== Espacio de no separación ==
{{LaTeX}} justifica de manera automática los párrafos, por lo que una vez que se llene una línea mandará lo que sigue a la línea de abajo, separando palabras que, en ocasiones, sería mejor mantener juntas. Para conseguir que {{LaTeX}} no separe dos palabras con un cambio de línea debemos usar el comando ~. Por ejemplo, debemos escribir
<syntaxhighlight lang="latex">O.~Wilde escribió obras como...</syntaxhighlight>
para que no haya un salto entre "O." y "Wilde".
== Sangría de primera línea y espacio entre párrafos ==
Para ajustar la sangría de la primera línea, hay que modificar el parámetro \parindent. Por ejemplo, se deja un cuadratín con:
\setlength{\parindent}{1em}
Y se suprime con:
\setlength{\parindent}{0pt}
El espacio entre párrafos se ajusta con \parskip:
\setlength{\parskip}{10pt}
== Espacios tras punto ==
A menos que se use babel con la opción spanish, de manera automática {{LaTeX}} deja un espacio adicional después de un punto, según la tradición tipográfica anglosajona,<ref>Sin embargo, el paquete <syntaxhighlight lang="latex" enclose="none">babel</syntaxhighlight> en su opción castellana sigue la tradición tipográfica europea de no usar espacios extra después de un punto. Por tanto, ahorra todos estos problemas con las abreviaturas.</ref> a menos que éste esté precedido por una mayúscula, caso en el cual {{LaTeX}} interpreta el punto como el de una abreviatura y no deja ningún espacio adicional. Si una abreviatura termina con una letra minúscula, como por ejemplo la abreviatura latina "e. g.", entonces hemos de evitar el espacio adicional que dejará {{LaTeX}}. Esto se consigue con el comando <syntaxhighlight lang="latex" enclose="none">\ </syntaxhighlight>. Por ejemplo, debemos escribir
<syntaxhighlight lang="latex">...existen clases (e.~g.\ la clase de todos los conjuntos) que no son conjuntos</syntaxhighlight>
Si una frase termina con mayúscula, {{LaTeX}}, como ya hemos dicho, no dejará un espacio adicional después del punto que termina dicha frase por considerarlo el de una abreviatura. Para indicarle a {{LaTeX}} que se trata efectivamente del punto que termina una frase debemos escribir el comando <syntaxhighlight lang="latex" enclose="none">\@</syntaxhighlight>. Por ejemplo, debemos escribir
<syntaxhighlight lang="latex">Podemos compilar nuestros documentos en formato PDF\@. Además, están los formatos...</syntaxhighlight>
== Espacios con extensión infinita ==
Otra opción más para espacios horizontales son los comandos que "empujan" el texto hasta el final de la página. Por ejemplo, el comando <syntaxhighlight lang="latex" enclose="none">\hfill</syntaxhighlight> empuja el texto dejando espacios en blanco, como en el siguiente ejemplo:
<syntaxhighlight lang="latex" enclose="none">Desde este punto\hfill hasta este punto</syntaxhighlight>
produce:
[[Archivo:Hfill.svg|820px|Desde este punto\hfillhasta este otro]]
Si en lugar de <syntaxhighlight lang="latex" enclose="none">hfill</syntaxhighlight> escribimos <syntaxhighlight lang="latex" enclose="none">\hrulefill</syntaxhighlight> o <syntaxhighlight lang="latex" enclose="none">\dotfill</syntaxhighlight> obtenemos, respectivamente:
[[Archivo:Hrulefill.svg|820px|Desde este punto\hrulefill hasta este otro]]
y
[[Archivo:Dotfill.svg|820px|Desde este punto\dotfill hasta este otro]]
== Blancos verticales ==
Por otra parte, una o más líneas en blanco en el texto fuente producen una sóla línea en blanco en el texto compilado.
{|align="center"
|Así, si escribimos:
|width="25px" |
|obtenemos:
|-
|
|
|-
|valign="top" |{{Verb|Primera línea.
Aún estamos en la misma línea.}}
<syntaxhighlight lang="latex" enclose="none">Esta es la segunda línea</syntaxhighlight>
<syntaxhighlight lang="latex" enclose="none">Esta es la tercera línea</syntaxhighlight>
|
|valign="top" |Primera línea. Aún estamos en la misma línea.
Esta es la segunda línea
Esta es la tercera línea.
|}
Podemos usar también el comando <syntaxhighlight lang="latex" enclose="none">\vspace{''valor''}</syntaxhighlight>, con un efecto similar al de <syntaxhighlight lang="latex" enclose="none">\hspace{} </syntaxhighlight> salvo que el espacio es vertical. Para espacios verticales predefinidos, podemos usar los comandos
{|align="center"
|<syntaxhighlight lang="latex" enclose="none">\smallskip</syntaxhighlight>
|width="20px" |
|<syntaxhighlight lang="latex" enclose="none">\medskip</syntaxhighlight>
|width="20px" |
|<syntaxhighlight lang="latex" enclose="none">\bigskip</syntaxhighlight>
|}
Es posible también dejar cierto blanco cuando se hace un salto de línea con \\ añadiendo una dimensión entre paréntesis: <syntaxhighlight lang="latex" enclose="none">\\[''valor'']</syntaxhighlight> produce un espacio entre líneas igual al ''valor'' especificado. Recuérdese que esta orden no es para crear espacios entre párrafos, sino solo cuando para los casos, no muy habituales, en los que hay un salto de línea dentro de un párrafo. De hecho, su uso para aumentar el espacio entre párrafos es un error (habitual).
== Referencias ==
{{listaref}}
{{Notapie}}
{{AutoCat}}
tvifn1m3kg42e7tgwcfhkthh8q013gw
Manual de LaTeX/Escribiendo texto/Caracteres especiales
0
15206
436537
385192
2026-10-15T07:46:51Z
Antimundo
74354
Categorizar usando AutoCat
436537
wikitext
text/x-wiki
Ya hemos visto que {{LaTeX}} reserva ciertos símbolos de código ASCII para funciones especiales (e.g. la barra invertida \ para iniciar un comando, la tilde ~ para evitar particiones de palabras, etc). He aquí todos los caracteres que tienen una función especial en {{LaTeX}}:
{|width="70%" align="center"
|<syntaxhighlight lang="latex" enclose="none">$</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">#</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">%</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">&</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">^</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">_</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">{</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">}</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">~</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\</syntaxhighlight>
|}
Si queremos que aparezcan como simples símbolos en el texto compilado, hemos de escribir
{|width="70%" align="center"
|<syntaxhighlight lang="latex" enclose="none">\$</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\#</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\%</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\&</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\^</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\_</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\{</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\}</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\~</syntaxhighlight>
|<syntaxhighlight lang="latex" enclose="none">\textbackslash</syntaxhighlight>
|}
Algunos paquetes también interpretan de modo especial ciertos caracteres. El caso más significativo es babel, en el que las comillas rectas " introducen lo que se llaman shorthands o abreviaciones. Obsérvese que este carácter no debe usarse para introducir comillas en ningún caso, aunque no se haya cargado babel. Así, con spanish para babel "n equivale a ñ, "o es el ordinal, "+-- es una raya, etc.
{{AutoCat}}
9ovc96za18mngcrt9h03fm1zom5zxw6
Manual de LaTeX/Escribiendo texto/Tamaños, estilos y tipos de letra
0
15207
436544
414982
2026-10-15T07:47:57Z
Antimundo
74354
Categorizar usando AutoCat
436544
wikitext
text/x-wiki
En {{LaTeX}} las letras (o fuentes) tienen en general 5 atributos, aunque sólo mencionaremos cuatro de ellos, que son los que determinan el aspecto del caracter en el texto compilado.
Para los cambios breves de la fuente, lo recomendable es:
Este es un texto que puede tener \textit{cursiva} y también \textbf{negrita}.
También puede ser \textit{\textbf{cursiva con negrita}}. Otra posibilidad
es la \textsc{versalita}.
La conversión de caja se obtiene con \MakeUppercase{texto} (que convierte a mayúscula) y \MakeLowercase{TEXTO} (a minúscula). (No deben usarse en LaTeX las órdenes \uppercase y \lowercase, aunque las admita, porque no siempre dan el resultado correcto.)
== Familia ==
La '''familia''' es el nombre de una colección de fuentes. {{LaTeX}} organiza las fuentes en tres familias, que son <font style="vertical-align:3px"> </font>, <font style="vertical-align:3px">[[Imagen:Sans_Serif.svg]]</font>, y <font style="vertical-align:1px">[[Imagen:Typewriter.svg|50px]]</font>. Para conseguir cada una de estas familias se usan, respectivamente, los comandos <syntaxhighlight lang="latex" enclose="none">\rmfamily</syntaxhighlight> (letras con remates), <syntaxhighlight lang="latex" enclose="none">\sffamily</syntaxhighlight> (letras sin remates) y <syntaxhighlight lang="latex" enclose="none">\ttfamily</syntaxhighlight> (letras mecanográficas). Estos comandos son en realidad ''declaraciones'', por lo que su efecto se limita de manera distinta a la de los comandos comunes. Por ejemplo, si queremos conseguir un texto con caracteres <font style="vertical-align:1px">[[Imagen:Typewriter.svg|50px]]</font>, debemos escribir
<syntaxhighlight lang="latex">{\ttfamily ''texto''}</syntaxhighlight>
:y así el efecto de <syntaxhighlight lang="latex" enclose="none">\ttfamily</syntaxhighlight> afectará sólo al texto que se encuentre entre llaves.
[[File:Computer_modern.jpg|thumb|right|200px|Muestras de la familia Computer Modern]]
Las fuentes preferminadas de LaTeX perteneces a la familia Computer Modern, pero podrían cambiarse a otras como, respectivamente, Times, Helveticas y Courier, por ejemplo. Para ello lo recomendado es cargar algún paquete, pero para emplear una fuente arbitraria instalada en el sistema es necesario recurrir a dos variantes de TeX llamadas XeTeX y LuaTeX. X
== Serie ==
La '''serie''' de una fuente determina que tan gruesa o expandida será ésta. Con {{LaTeX}} tenemos la opción Medium (media) y la opción '''Bold''' (negrita). Caracteres con este tipo de series se consiguen, respectivamente, con las declaraciones <syntaxhighlight lang="latex" enclose="none">\mdseries</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">bfseries</syntaxhighlight>. Como éstas también son declaraciones, para obtener, por ejemplo, un texto en negritas hemos de escribir <syntaxhighlight lang="latex" enclose="none">{\bfseries ''texto''}</syntaxhighlight>.
== Forma ==
La '''forma''' que puede tener un caracter dentro de una familia puede ser: <font style="vertical-align:1px">[[Imagen:Upright.svg]]</font> (vertical o recta), <font style="vertical-align:2px">[[Imagen:Italic.svg]]</font> (itálica), <font style="vertical-align:2px">[[Imagen:Slanted.svg]]</font> (inclinada) o <font style="vertical-align:2px">[[Imagen:Small_Caps.svg]]</font> (Mayúsculas y mayúsculas pequeñas). Estas formas se consiguen con las declaraciones <syntaxhighlight lang="latex" enclose="none">\upshape</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\itshape</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\slshape</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">\scshape</syntaxhighlight>, respectivamente. Además, tenemos los comandos
{|align="center"
|<syntaxhighlight lang="latex" enclose="none">\textbf{''texto''}</syntaxhighlight>:
|para texto en negritas
|-
|<syntaxhighlight lang="latex" enclose="none">\textit{''texto''}</syntaxhighlight>:
|para texto en itálicas
|-
|<syntaxhighlight lang="latex" enclose="none">\textsl{''texto''}</syntaxhighlight>:
|para texto inclinado
|-
|<syntaxhighlight lang="latex" enclose="none">\texttt{''texto''}</syntaxhighlight>:
|para texto en estilo <font style="vertical-align:1px">[[Imagen:Typewriter.svg|50px]]</font>
|-
|<syntaxhighlight lang="latex" enclose="none">\textsc{''texto''}</syntaxhighlight>:
|para texto en mayúsculas y minúsculas pequeñas
|}
''Nota.'' Aunque LaTeX no dé error con las órdenes de Plain TeX \bf, \it, \sf, etc., no deberían usarse en lugar de las recién descritas.
== Tamaño ==
El tamaño de una letra puede ser
<div align="center">
{|{{Tablabonita}}
|[[Imagen:Tinysize.png|33px|{\tiny tiny}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\tiny</syntaxhighlight>
|-
|[[Imagen:Script_size.png|80px|<syntaxhighlight lang="latex" enclose="none">{\scriptsize scriptsize}</syntaxhighlight>]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\scriptsize</syntaxhighlight>
|-
|[[Imagen:Small.png|54px|{\small small}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\small</syntaxhighlight>
|-
|[[Imagen:Normal.png|71px|{\normalsize normalsize}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\normalsize</syntaxhighlight>
|-
|
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\large</syntaxhighlight>
|-
|[[Imagen:Larger.png|{\Large larger}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\Large</syntaxhighlight>
|-
|[[Imagen:Largest.png|{\LARGE LARGE}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\LARGE</syntaxhighlight>
|-
|[[Imagen:Huge.png|85px|{\huge huge}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\huge</syntaxhighlight>
|-
|[[Imagen:Hugger.png|112px|{\Huge Huge}]]
|style="padding-left:10px" | que se consigue con la declaración <syntaxhighlight lang="latex" enclose="none">\Huge</syntaxhighlight>
|}
</div>
Estas órdenes no solo ajustan el tamaño de la letra, sino también la interlínea y en ocasiones también otros parámetros relacionados con listas y ecuaciones. Un error habitual es escribir un párrafo del siguiente modo:
{\small
Texto texto texto
texto texto.}
Aunque con ello se cambia el tamaño de la letra, la interlínea sigue igual. Es necesario señalar un párrafo con, por ejemplo:
{\small
Texto texto texto
texto texto.\par}
{{AutoCat}}
6jteb2088js91gosj5o8dfergk2x8n6
Manual de LaTeX/Escribiendo texto/Alineación del texto
0
15218
436533
385191
2026-10-15T07:45:10Z
Antimundo
74354
Categorizar usando AutoCat
436533
wikitext
text/x-wiki
{{LaTeX}} automáticamente justifica los párrafos (es decir, los alinea por ambos lados), aunque podemos alinear el texto solo por la izquierda con la declaración <syntaxhighlight lang="latex" enclose="none">\raggedright</syntaxhighlight>(bandera por la derecha) y solo por la derecha con la declaración <syntaxhighlight lang="latex" enclose="none">\raggedleft</syntaxhighlight> (bandera por la izquierda). Para centrar el texto hemos de usar la declaración <syntaxhighlight lang="latex" enclose="none">\centering</syntaxhighlight>.
Alternativamente podemos usar los entornos de alineación <syntaxhighlight lang="latex" enclose="none">flushleft</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">flushright</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">center</syntaxhighlight>. Puesto que estos son entornos, para, por ejemplo, centrar texto con <syntaxhighlight lang="latex" enclose="none">center</syntaxhighlight> debemos escribir
<syntaxhighlight lang="latex" enclose="none">\begin{center}</syntaxhighlight>
<syntaxhighlight lang="latex" enclose="none">Texto centrado</syntaxhighlight>
<syntaxhighlight lang="latex" enclose="none">\end{center}</syntaxhighlight>
{{AutoCat}}
fgzvgubfhqp29wzrrfftjpjvkp5zah9
Manual de LaTeX/Escribiendo texto/Partición de palabras
0
15219
436540
385194
2026-10-15T07:47:21Z
Antimundo
74354
Categorizar usando AutoCat
436540
wikitext
text/x-wiki
Al justificar el texto, {{LaTeX}} partirá las palabras que ya no quepan completas en una línea. Para ello, basta con cargar el paquete babel con la opción spanish:
<syntaxhighlight lang="latex" enclose="none">\usepackage[spanish]{babel}</syntaxhighlight>
En algunas ocasiones, raras, no siempre lo hace del modo correcto (en especial en voces compuestas y prefijadas). Para indicarle a {{LaTeX}} la forma en que debe partir una palabra en particular usamos el comando <syntaxhighlight lang="latex" enclose="none">\hyphenation</syntaxhighlight>. Por ejemplo, para indicar a {{LaTeX}} como debe partir las palabras "neoortodoxia" y "bioaerosol" escribimos:
<syntaxhighlight lang="latex" enclose="none">\hyphenation{neo-or-to-do-xia bio-ae-ro-sol}</syntaxhighlight>
Si escribimos esto en el preámbulo del documento, las reglas de partición de esas palabras quedarán grabadas en las reglas de partición del lenguaje que estemos usando. Como mencionábamos, una especificación de partición para una palabra con el comando <syntaxhighlight lang="latex" enclose="none">\hyphenation</syntaxhighlight> en el preámbulo hará que las reglas de partición que has dado para esa palabra se guarden en las reglas de partición del lenguaje "Spanish".
Otra forma de indicar cómo debe partirse una palabra es mediante el comando <syntaxhighlight lang="latex" enclose="none">\-</syntaxhighlight>. Por ejemplo, si te das cuenta que en la compilación de tu documento la palabra "incomible" está mal particionada, ve hacia ella en el texto fuente e indica la forma correcta, reemplazando la palabra <syntaxhighlight lang="latex" enclose="none">incomible</syntaxhighlight> por <syntaxhighlight lang="latex" enclose="none">in\-co\-mi\-ble</syntaxhighlight>. Pero es un último recurso que conviene evitar en general.
Para que {{LaTeX}} no parta una palabra en algún punto, se usa <syntaxhighlight lang="latex" enclose="none">\mbox{}</syntaxhighlight>. Por ejemplo, si se escribe<syntaxhighlight lang="latex" enclose="none">Dr.~\mbox{Knuth}</syntaxhighlight>, {{LaTeX}} siempre escribirá Dr. Knuth sin partir esta última palabra (no debería haber espacios dentro de esta orden, pues no se ajustaría al tamaño apropiado cuando se justifica el texto). Aquí, ~ es un espacio de no división.
{{AutoCat}}
lc3dac7ohw6eob6j5c4qojf3h3djy54
Manual de LaTeX/Escribiendo texto/Signos ortográficos
0
15220
436542
411679
2026-10-15T07:47:44Z
Antimundo
74354
Categorizar usando AutoCat
436542
wikitext
text/x-wiki
Para obtener los signos ortográficos del castellano (y otros más) es necesario usar el paquete <syntaxhighlight lang="latex" enclose="none">inputenc</syntaxhighlight>. Si en el preámbulo escribimos
<center><syntaxhighlight lang="latex">\usepackage[latin1]{inputenc}</syntaxhighlight></center>
cambiamos la codificación de la entrada de {{LaTeX}} a latin1 (usada por ejemplo en Unix) y podremos escribir las palabras acentuadas tales y cuales, es decir, <syntaxhighlight lang="latex" enclose="none">á, Á, ñ, Ñ</syntaxhighlight> nos dará á, Á, ñ, Ñ en el documento compilado. También se pueden escribir otros caracteres como «», “”, ¿, ¡, etc. Otros valores característicos son:
* En Windows:
<syntaxhighlight lang="latex">\usepackage[cp1252]{inputenc}</syntaxhighlight>
* En Mac:
<syntaxhighlight lang="latex">\usepackage[applemac]{inputenc}</syntaxhighlight>
Aunque cada vez es más frecuente el uso de editores de Unicode que guardan en UTF-8:
<syntaxhighlight lang="latex">\usepackage[utf8]{inputenc}</syntaxhighlight>
Además, para que el resultado sea óptimo, es necesario establecer también una codificación apropiada de las fuentes con fontenc. Para el español, el valor recomendado en T1:
<syntaxhighlight lang="latex">\usepackage[T1]{fontenc}</syntaxhighlight>
Cierto número de signos y símbolos requieren un paquete adicional:
<syntaxhighlight lang="latex">\usepackage{textcomp}</syntaxhighlight>
No son raros los errores por un ajuste indebido de la codificación. Un mensaje como el siguiente suele indicar un error de este tipo:
Package inputenc Error: Unicode char \u8:ä not set up for use with LaTeX
Un sistema más seguro para seleccionar la codificación, que da resultados correctos incluso si se recodifica un archivo, es el siguiente:
\documentclass{article}
\usepackage{selinput}
\SelectInputMappings{
aacute={á},
ntilde={ñ},
Euro={€}
}
\usepackage[T1]{fontenc}
\begin{document}
áéíóú
\end{document}
Con XeTeX y LuaTeX no es necesario, en principio, ningún paquete, siempre que el documento fuente esté en UTF-8. Es posible que tu editor utilize por defecto la familia de fuentes Computer Modern (que tiene un conjunto de caracteres limitado y no apto para el español), por lo cuál querrás usar otro conjunto de fuentes, como Latin Modern. Una forma fácil de hacerlo es agregar el paquete `fontspec` que por defecto define como fuente a Latin Modern:
\usepackage{fontspec}
En LaTeX también es posible un marcado lógico: así, spanish para babel proporciona las abreviaciones <code><< >></code> para comillas genéricas (similar al elemento q de HTML). El tipo de comilla («»“”‘’) es configurable (en España puede ser «» y en México “”, por ejemplo) y dependerá del contexto. Otra opción para las comillas es el paquete csquotes.
== ASCII puro ==
{{LaTeX}} originalmente solo leía texto de código ASCII, por lo que para usar palabras acentuadas, se necesitaban algunas instrucciones. Desde hace muchos años (inputenc y fontenc datan de 1994) no es necesario y el empleo de los métodos descritos a continuación no resultan por lo general convenientes, pero se dan como referencia para trabajar con documentos antiguos y con ciertas tareas internas y especiales.
He aquí la forma de conseguir acentuaciones y signos ortográficos que no tienen un ASCII:
<div align="center">
{|{{Tablabonita}}
|<syntaxhighlight lang="latex" enclose="none">\'</syntaxhighlight>
|´ (acento agudo)
|<syntaxhighlight lang="latex" enclose="none">\`</syntaxhighlight>
|` (acento grave)
|-
|<syntaxhighlight lang="latex" enclose="none">\~</syntaxhighlight>
|~ (virgulilla)
|<syntaxhighlight lang="latex" enclose="none">\"</syntaxhighlight>
|¨ (diéresis)
|-
|<syntaxhighlight lang="latex" enclose="none">\^</syntaxhighlight>
|^ (circunflejo)
|<syntaxhighlight lang="latex" enclose="none">\c c</syntaxhighlight>
|ç (c con cedilla)
|-
|<syntaxhighlight lang="latex" enclose="none">?`</syntaxhighlight>
|¿ (signo izquierdo de interrogación)
|<syntaxhighlight lang="latex" enclose="none">!`</syntaxhighlight>
|¡ (signo izquierdo de exclamación)
|}
</div>
Así, para obtener palabras como conexión escribimos <syntaxhighlight lang="latex" enclose="none">conexi\'on</syntaxhighlight>. La acentuación de la letra i requiere de un paso previo, que consiste en eliminar el puntito que ha de ser remplazado por el acento. Pare esto escribimos <syntaxhighlight lang="latex" enclose="none">\i</syntaxhighlight>. Así, al escribir <syntaxhighlight lang="latex" enclose="none">\'{\i}</syntaxhighlight> obtenemos í.
Para obtener comillas se usan el acento grave (<syntaxhighlight lang="latex" enclose="none">`</syntaxhighlight>), que nos da ‘, y el apóstrofo (<syntaxhighlight lang="latex" enclose="none">'</syntaxhighlight>), que nos da ’. Así, por ejemplo, con
<center><syntaxhighlight lang="latex">Él dijo que había dicho la ``verdad''</syntaxhighlight></center>
obtenemos Él dijo que había dicho la “verdad”.
Hay símbolos que no están definidos de manera inmediata en {{LaTeX}}, pero que podemos conseguir muy fácilmente. Por ejemplo, el símbolo de grado, º, podemos obtenerlo con <syntaxhighlight lang="latex" enclose="none">$^{\circ}$</syntaxhighlight>. Sería aún mejor si definimos nuestro propio comando para obtener el símbolo que hemos creado. Por ejemplo, podemos escribir (de preferencia en el preámbulo),
<center><syntaxhighlight lang="latex">\newcommand{\grad}{$^{\circ}$}</syntaxhighlight></center>
y así, al escribir <syntaxhighlight lang="latex" enclose="none">La temperatura era de 47 \grad C</syntaxhighlight> obtendremos La temperatura era de 47ºC
También podemos escribir <syntaxhighlight lang="latex" enclose="none">La temperatura era de $47^{\circ}$C</syntaxhighlight> Obtendremos el mismo resultado.
En las últimas versiones del paquete babel es posible escribir ordinales con 1"o, 2"a, etc. para conseguir 1.º, 2.º, etc.
Referencias
<span style="color: red; text-decoration: line-through;"> http://www.tex-tipografia.com/archive/spanish.pdf</span> (Enlace no funciona)
{{AutoCat}}
anjfz2q5tuyd3reta03yqptj6awgcx9
Manual de LaTeX/La estructura de un documento en LaTeX/Cuerpo/Portada del documento
0
15222
436557
385200
2026-10-15T07:50:16Z
Antimundo
74354
Categorizar usando AutoCat
436557
wikitext
text/x-wiki
En todas las clases estándar de documento de {{LaTeX}} podemos introducir el título y autor del mismo, así como también la fecha. Para el título se usa la instrucción <syntaxhighlight lang="latex" enclose="none">\title{''título del documento''}</syntaxhighlight> y para el nombre del autor se usa <syntaxhighlight lang="latex" enclose="none">\author{''nombre del autor''}</syntaxhighlight>. La fecha se escribe con el comando <syntaxhighlight lang="latex" enclose="none">\date{''fecha''}</syntaxhighlight>. Si omitimos esta orden (o escribimos <syntaxhighlight lang="latex" enclose="none">\date{\today}</syntaxhighlight>) aparecerá la fecha en que se compila el documento. Todas estas instrucciones se escriben en el preámbulo, y para que aparezcan impresos en el documento compilado debemos escribir
<center><syntaxhighlight lang="latex">\maketitle</syntaxhighlight></center>
inmediatamente después de iniciar el cuerpo del documento (i.e. justo después de <syntaxhighlight lang="latex" enclose="none">\begin{document}</syntaxhighlight>).
Si usamos la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> o la clase <syntaxhighlight lang="latex" enclose="none">report</syntaxhighlight> el título aparecerá al principio y en una página aparte. En cambio, con la clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight> el título aparecerá en la parte superior de la primera página del documento. Si queremos que en la clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight> aparezca el título en una página aparte, debemos especificar la opción <syntaxhighlight lang="latex" enclose="none">titlepage</syntaxhighlight>, que está desactivada por defecto.
El tamaño de letra del título es <syntaxhighlight lang="latex" enclose="none">\LARGE</syntaxhighlight>, pero puede ser cambiada dentro de <syntaxhighlight lang="latex" enclose="none">\title{}</syntaxhighlight>. Por ejemplo, con las líneas
<syntaxhighlight lang="latex">\documentclass{book}
\title{\Huge Composici\'on de textos con \LaTeXe}
\author{Los Wikiescritores}
\date{}
\begin{document}
\maketitle
\end{document}
</syntaxhighlight>
obtenemos la página de título siguiente:
[[File:WikibookLatexPortada.png|350px|standard LaTeX titlepage]]
=¿Qué hacemos si queremos una portada diferente?=
Una opción es sustituir <code>\maketitle</code> por el entorno <code>titlepage</code>. Un ejemplo práctico:
<syntaxhighlight lang="latex">
\documentclass[12pt,a4paper]{report}
\usepackage{graphicx}
\begin{document}
\begin{titlepage}
\centering
\includegraphics[width=0.15\textwidth]{example-image-1x1}\par\vspace{1cm}
{\scshape\LARGE Columbidae University \par}
\vspace{1cm}
{\scshape\Large Final year project\par}
\vspace{1.5cm}
{\huge\bfseries Pigeons love doves\par}
\vspace{2cm}
{\Large\itshape John Birdwatch\par}
\vfill
supervised by\par
Dr.~Mark \textsc{Brown}
\vfill
% Bottom of the page
{\large \today\par}
\end{titlepage}
\end{document}</syntaxhighlight>
[[File:TitlepageWikibook.png|TitlepageWikibook]]
{{AutoCat}}
[[pt:Latex/Título]]
[[en:LaTeX/Title Creation]]
[[de:LaTeX/_Eine_Titelseite_erstellen]]
[[zh:LaTeX/生成封面和标题]]
[[sr:LaTeX/Стварање наслова]]
e16pbzi8ekwzm8093mbr3ns8hw2oxre
Manual de LaTeX/La estructura de un documento en LaTeX/Cuerpo/Secciones de un documento
0
15224
436558
385201
2026-10-15T07:50:23Z
Antimundo
74354
Categorizar usando AutoCat
436558
wikitext
text/x-wiki
Aunque un documento en LaTeX puede tener una estructura por secciones casi arbitraria, normalmente se siguen las divisiones de las clases estándar. Con article puede dividirse en secciones, subsecciones, párrafos y subpárrafos. Con las clases <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">report</syntaxhighlight> podemos incluir también capítulos.
Para iniciar un capítulo usamos el comando
<syntaxhighlight lang="latex">\chapter{''nombre del capítulo''}</syntaxhighlight>
Similarmente se usan los comandos <syntaxhighlight lang="latex" enclose="none">\section{}</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\subsection{}</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\paragraph{}</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">\subparagraph{}</syntaxhighlight> para secciones, subsecciones, etc. Cabe mencionar que la numeración de cada una de estas partes del documento la realiza {{LaTeX}} por sí solo.
Hay ocasiones en que el título de una sección es muy largo. En estos casos, el encabezado con el nombre de la sección sobrepasa el tamaño de la página, por lo que es conveniente contar con un método para que el nombre de la sección aparezca abreviado en el encabezado de la página. Por ello, la forma general del comando para secciones que provee {{LaTeX}} es el siguiente:
<syntaxhighlight lang="latex">\section[''nombre corto de la sección'']{nombre de la sección}</syntaxhighlight>
En particular, la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight> permite dividir el documento en partes, cada una de ellas obtenidas con el comando <syntaxhighlight lang="latex" enclose="none">\part{}</syntaxhighlight>. Además, esta clase de documento incluye nuevas características en {{LaTeX|2e}}, como lo son los comandos
<syntaxhighlight lang="latex" enclose="none">\frontmatter</syntaxhighlight>
<syntaxhighlight lang="latex" enclose="none">\mainmatter</syntaxhighlight>
<syntaxhighlight lang="latex" enclose="none">\backmatter</syntaxhighlight>
que dan estructura al documento. Con <syntaxhighlight lang="latex" enclose="none">\frontmatter</syntaxhighlight> damos el estilo que deben tener los principios, es decir, la portada, la tabla de contenidos, los prólogos..., con <syntaxhighlight lang="latex" enclose="none">\mainmatter</syntaxhighlight> damos el estilo que debe tener el texto principal del documento, y finalmente <syntaxhighlight lang="latex" enclose="none">\backmatter</syntaxhighlight> se usa para el estilo de las finales, es decir, parte final del libro (la bibliografía, los índices alfabético, colofón...).
Todo lo que quede contenido entre <syntaxhighlight lang="latex" enclose="none">\frontmatter</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">\mainmatter</syntaxhighlight> (que se supone debe de ser la parte frontal del libro), tendrá un estilo en el que la numeración de página es con números romanos, y ningún capítulo, ni ningún otro título de nivel inferior, será numerado. Las páginas después de <syntaxhighlight lang="latex" enclose="none">\mainmatter</syntaxhighlight> serán numeradas con números arábigos y los capítulos y títulos de nivel inferior sí serán numerados. Con <syntaxhighlight lang="latex" enclose="none">\backmatter</syntaxhighlight> hacemos que los capítulos y títulos nivel inferior no aparezcan numerados (lo que es ideal para conclusiones o notas finales). Estos ajustes se pueden modificar por diversas vías.
{{AutoCat}}
4ilwsc4ddpdtoutfgz9vbk6y94j1858
Manual de LaTeX/La estructura de un documento en LaTeX/Cuerpo/Estilos de página
0
15255
436556
385199
2026-10-15T07:50:00Z
Antimundo
74354
Categorizar usando AutoCat
436556
wikitext
text/x-wiki
La numeración de páginas y la impresión de encabezados en las mismas constituyen el estilo de la página. Cambios en el estilo de página pueden realizarse con el comando
<syntaxhighlight lang="latex">\pagestyle{''estilo''}</syntaxhighlight>
Los estilos que ofrecen las clases de documento estándar de {{LaTeX}} son <syntaxhighlight lang="latex" enclose="none">empty</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">plain</syntaxhighlight> y <syntaxhighlight lang="latex" enclose="none">headings</syntaxhighlight>. Con <syntaxhighlight lang="latex" enclose="none">\pagestyle{empty}</syntaxhighlight> hacemos que las páginas queden sin número de página ni encabezado; con <syntaxhighlight lang="latex" enclose="none">\pagestyle{plain}</syntaxhighlight>, que es el estilo por defecto, obtenemos páginas numeradas, pero sin encabezado; con <syntaxhighlight lang="latex" enclose="none">\pagestyle{headings}</syntaxhighlight> obtenemos páginas numeradas y con encabezado. Más específicamente, <syntaxhighlight lang="latex" enclose="none">\pagestyle{headings}</syntaxhighlight> produce efectos distintos según la clase de documento y las opciones que para ella se especifiquen. Por ejemplo, con la clase <syntaxhighlight lang="latex" enclose="none">article</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\pagestyle{headings}</syntaxhighlight> nos dará el número de página al pie y un encabezado con el nombre de la sección, y si hemos elegido la opción <syntaxhighlight lang="latex" enclose="none">twoside</syntaxhighlight>, el encabezado será el nombre de la sección en las páginas pares y el nombre de la subsección en las páginas impares. Para el caso de la clase <syntaxhighlight lang="latex" enclose="none">book</syntaxhighlight>, <syntaxhighlight lang="latex" enclose="none">\pagestyle{headings}</syntaxhighlight> pondrá el número de página en la parte exterior de la cabecera (lado izquierdo en páginas pares y lado derecho en páginas impares) y el encabezado (que será el nombre del capítulo en páginas pares y el nombre de la sección en páginas impares) en la parte interior de la cabecera.
Si queremos cambiar el estilo de una página en particular, usamos
<syntaxhighlight lang="latex">\thispagestyle{''estilo''}</syntaxhighlight>
que toma los mismos valores que <syntaxhighlight lang="latex" enclose="none">\pagestyle{}</syntaxhighlight>.
Para especificar por nuestra propia cuenta que es lo que aparecerá en la cabecera, podemos usar la instrucción
<syntaxhighlight lang="latex">\pagestyle{myheadings}</syntaxhighlight>
que pondrá los encabezados según estos estén indicados con los comandos
<syntaxhighlight lang="latex" enclose="none">\markboth{''encabezado izquierdo''}{''encabezado derecho''}</syntaxhighlight>
y
<syntaxhighlight lang="latex" enclose="none">\markright{''encabezado derecho''}</syntaxhighlight>
Notar que con la opción de clase <syntaxhighlight lang="latex" enclose="none">oneside</syntaxhighlight>, los encabezados sólo pueden ser los derechos (pues no hay páginas que estén a la izquierda).
Al utilizar el estilo <syntaxhighlight lang="latex" enclose="none">\pagestyle{headings}</syntaxhighlight>, vemos que la letra del encabezado aparece en caracteres inclinados y en mayúsculas. Esto se debe a que las clases de documento estándar de {{LaTeX}} así lo definen. Para reajustar los encabezados y los pies, en lo que respecta a las mayúsculas y en otros detalles, hay dos paquetes útiles: fancyhdr y titleps. Un ejemplo simple de este último es:
\newpagestyle{main}{
\sethead[\thepage][\chaptertitle][(\thesection] % pares
{\thesection)}{\sectiontitle}{\thepage}} % impares
\pagestyle{main}
{{AutoCat}}
sccqznp1yt8v6u6wewpjbkpnsel4zya
Manual de LaTeX/Gestionando la bibliografía/Notas al pie
0
15487
436546
385197
2026-10-15T07:48:24Z
Antimundo
74354
Categorizar usando AutoCat
436546
wikitext
text/x-wiki
La forma más sencilla de incluir notas a pie de página en {{LaTeX}} es usando:
<syntaxhighlight lang="latex" enclose="none">\footnote{''nota al pie''}</syntaxhighlight>
Por ejemplo, si escribimos
<syntaxhighlight lang="latex" enclose="none"> ... y, de hecho, el mal entendimiento respecto del carácter puramente existencial del axioma de elección ha llevado a muchas discusiones estériles durante algunas décadas\footnote{cf. F. P. Ramsey. \textit{The foundations of Mathematics}, London Mathematical Society.}</syntaxhighlight>
En realidad, la instrucción general para poner notas al pie de página es la siguiente:
<center><syntaxhighlight lang="latex">\footnote[''marca'']{''nota al pie''}</syntaxhighlight></center>
El valor opcional determina el tipo de marca de la nota al pie. Por ejemplo, si queremos que la marca de nuestra nota al pie sea 3, entonces escribimos <syntaxhighlight lang="latex" enclose="none">\footnote[3]{''nota al pie''}</syntaxhighlight>.
Más aún, podemos cambiar el tipo de numeración de las notas al pie como sigue:
{|
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\arabic{footnote}}</syntaxhighlight>
|
| Numeración arábiga: 1, 2, 3...
|-
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\roman{footnote}}</syntaxhighlight>
|
| Numeración romana en minúsculas: i, ii, iii...
|-
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\Roman{footnote}}</syntaxhighlight>
|
| Numeración romana en mayúsculas: I, II, III...
|-
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\alph{footnote}}</syntaxhighlight>
|
| Numeración alfabética en minúsculas a, b, c...
|-
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\Alph{footnote}}</syntaxhighlight>
|
| Numeración alfabética en mayúsculas: A, B, C...
|-
| <syntaxhighlight lang="latex" enclose="none">\renewcommand{\thefootnote}{\fnsymbol{footnote}}</syntaxhighlight>
|
| No números, sino símbolos diversos
|}
El largo y el ancho de la línea de la nota al pie está determinada por la definición del comando <syntaxhighlight lang="latex" enclose="none">\footnoterule</syntaxhighlight>. La definición original que da {{LaTeX}} de este comando equivale a la siguiente:
<syntaxhighlight lang="latex">
\newcommand{\footnoterule}{\vspace*{-3pt}
\noindent\rule{2in}{0.4pt}\vspace*{2.6pt}}
</syntaxhighlight>
Así, si queremos que la línea de la nota al pie tenga un largo de 5cm y un ancho de 1pt, escribimos en el preámbulo
<syntaxhighlight lang="latex">
\renewcommand{\footnoterule}{\vspace*{-3pt}
\noindent\rule{5cm}{1pt}\vspace*{2.6pt}}
</syntaxhighlight>
Con esta definición, el aspecto de la página del ejemplo anterior sería la siguiente:
<center>
[[Imagen:footnote2.svg]]
</center>
Las notas puede adoptar multitud de disposiciones, y no solo puede ir al pie sino también al margen o a final del capítulo (o del libro). Hay diversos paquetes que extienden las funciones básicas:
; bigfoot
: Múltiples series de notas, en espacial para aparatos críticos
; footmisc
: Numeración por páginas, notas en un párrafo (sin salto de línea entre ellas)
; yafoot
: Más utilidades para notas
; endnotes
: Notas al final de capítulo
{{AutoCat}}
qu9b0awt0zdu343m4t2w65vqxnzklxf
Manual de LaTeX/Introducción/Instalación/Instalación en OS X
0
16094
436550
328601
2026-10-15T07:48:58Z
Antimundo
74354
Categorizar usando AutoCat
436550
wikitext
text/x-wiki
Para '''Mac OSX''' (a partir de la versión 10.3) la instalación es sumamente sencilla, sólo hace falta seguir estos pasos:
# Visite la página http://www.tug.org/mactex/. En ella se encuentra un compendio con las mejores, más comunes y más usadas aplicaciones, llamada MacTex. Soporta TeX, LaTeX, AMSTeX, ConTeXt, XeTeX y muchos otros paquetes.
# Descargue el archivo MacTeX.dmg y proceda a una instalación común y corriente. i.e. doble click en el archivo descargado y seguir instrucciones.
El paquete MacTex contiene una distribución Tex Live 2007 completa de Tex, Ghostscipt, ImageMagick y los siguientes programas: TeXShop, LaTeXiT, BibDesk, Excalibur y i-Installer. Una instalación detallada permite a los usuarios pasar por alto algunos de estos paquetes si así lo desean.
Una vez instalado el paquete, se recomienda ponerlo todo en una única carpeta (llamada por ejemplo: Tex o LaTex, etc.) y dejarla en la carpeta Aplicaciones para mayor comodidad. También es recomendable leer el archivo README.rtf.
{{navegar
|libro=Manual de LaTeX
|actual=Introducción/Instalación/Instalación en OS X
|anterior=Introducción/Instalación
|siguiente=Introducción/Programas_complementarios
}}
{{AutoCat}}
j7i081d9t5gzs6ue4j7y3isdg3ajf6m
Manual de LaTeX/Gestionando la bibliografía/Citas
0
18321
436545
215279
2026-10-15T07:48:12Z
Antimundo
74354
Categorizar usando AutoCat
436545
wikitext
text/x-wiki
Para hacer las citas, sólo debemos escribir:
\begin{quote}
''texto citado''
\end{quote}
Recordemos que en ocasiones el tamaño de la fuente de la cita suele ser menor que el del texto normal, para esto sólo debemos:
\begin{quote}
\small ''texto citado''
\end{quote}
{{AutoCat}}
l6umw3jpa72ay42tyflq2jn7x1izmmc
Manual de LaTeX/Escribiendo texto/Tablas
0
20062
436543
426092
2026-10-15T07:47:50Z
Antimundo
74354
Categorizar usando AutoCat
436543
wikitext
text/x-wiki
En los libros escolares, las tablas son normalmente utilizadas para recapitular los resultados de una investigación. En general es necesario manejarlas bien para realizar documentos de buena calidad.
La gestión de tablas no es muy intuitiva. Las tablas de base son fáciles y presentables, utilizando la misma lógica que en HTML, pero una tabla un poco más elaborada requiere de cierto aprendizaje ya que no es muy intuitiva su construcción.
== El entorno ''tabular'' ==
Recordemos algunos conceptos ya explícitos.
; Entorno
: Un entorno es una declaración particular destinada a la composición de texto en un estilo específico. Todos los entornos empiezan y terminan de la misma manera:
\begin{nombre-entorno}
...
...
\end{nombre-entorno}
; Entorno <code>tabular</code>
: El entorno <code>tabular</code> es otro tipo de entorno, concebido para colocar los datos en las tablas. Ciertos parámetros son necesarios después de la declaración del entorno para describir la alineación de cada columna. No es necesario indicar el número de columnas porque se deduce a partir de los parámetros introducidos. De la misma manera, se pueden introducir líneas verticales entre columnas. Los símbolos siguientes están disponibles para describir las columnas de una tabla.
:* <code>l</code> : Columna alineada a la izquierda
:* <code>c</code> : Columna centrada
:* <code>r</code> : Columna alineada a la derecha
:* <code>p{''anchura''}</code> : Columna de anchura fija, justificada y con sangria; El texto esta posicionado en lo alto de la celda.
:* <code>m{''anchura''}</code> : Como en el caso anterior pero el texto esta centrado verticalmente.
:* <code>b{''anchura''}</code> : Como en el caso anterior, pero el texto esta posicionado en la parte baja de la celda.
<div id="array3">{{note| los parámetros <code>m</code> y <code>b</code> necesitan la utilización de la extensión <code>array</code>}}</div>
:* <code><nowiki>|</nowiki></code> : línea vertical
:* <code><nowiki>||</nowiki></code> : doble línea vertical
: Una vez en el entorno,
:* <code>&</code> : Separador de columna.
:* <code>\\</code> : Principio de una nueva línea.
:* <code>\hline</code> : Línea horizontal.
A tener en cuenta, que los espacios insertados entre estos comandos son inútiles, pero facilitan la lectura.
== Tabla de base ==
Este ejemplo muestra como crear una simple tabla en {{LaTeX}}. Es una tabla tres por tres, pero sin ninguna línea.
{|
| style="vertical-align: middle;" |
<pre>\begin{tabular}{ l c r }
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}</pre>
| style="vertical-align: middle;" |
[[Image:tableau_de_base1.png]]
|}
Modificando el ejemplo anterior añadiendo algunas líneas verticales:
{|
| style="vertical-align: middle;" |
<pre>\begin{tabular}{ l | c || r | }
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}</pre>
| style="vertical-align: middle;" |
[[Image:tableau_de_base2.png]]
|}
Para añadir las líneas horizontales superiores e inferiores:
{|
| style="vertical-align: middle;" |
<pre>\begin{tabular}{ l | c || r | }
\hline
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\hline
\end{tabular}</pre>
| style="vertical-align: middle;" |
[[Image:tableau_de_base3.png]]
|}
Y finalmente, para añadir líneas centradas entre todas las filas (ver la utilización del entorno <code>center</code>):
{|
| style="vertical-align: middle;" |
<pre>\begin{center}
\begin{tabular}{ l | c || r | }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & 6 \\ \hline
7 & 8 & 9 \\
\hline
\end{tabular}
\end{center}</pre>
| style="vertical-align: middle;" |
[[Image:tableau_de_base4.png]]
|}
== Texto en las tablas ==
Los algoritmos de {{LaTeX}} para generar las tablas tienen ciertas imperfecciones. Una de ellas es que no hará un salto de línea dentro de una celda, aunque se desborde la anchura de la página. Para las columnas que contendrán una cierta cantidad de texto, se recomienda emplear el atributo <code>p</code> e indicar la anchura deseada de la columna (aunque esto pueda obligar a efectuar varios ajustes antes de obtener el resultado previsto).
Antes de continuar, tenemos que presentar el sistema de medidas que {{LaTeX}} emplea. Es muy flexible para que se pueda elegir entre toda una variedad de unidades de medida
* <code>pt</code> : punto anglosajón, 1/72 de pulgada ;
* <code>mm</code> : milímetro ;
* <code>cm</code> : centímetro ;
* <code>in</code> : pulgada (2,54 cm) ;
* <code>ex</code> : altura d'x , altura de una letra sin el trazo vertical ni el palo inferior de la fuente utilizada;
* <code>em</code> : cuadratín, grosso modo la anchura de una '''M''' (capital) en la fuente utilizada.
Existen comandos conocidos con el nombre de ''commandos de longitud'', que juegan el rol de variable, que no tienen valores fijos porque dependen de la configuración de la clase y/o del preámbulo normal del documento.
Los mas útiles son:
* <code>\parindent</code> : El tamaño del desplazamiento a la derecha ;
* <code>\baselineskip</code> : Distancia vertical entre las líneas ;
* <code>\parskip</code> : Espacio suplementario entre los párrafos ;
* <code>\textwidth</code> : La anchura de una línea de texto en el entorno local (por ejemplo, las líneas son generalmente mas estrechas en el resumen que en el texto normal);
* <code>\textheight</code> : La altura del texto en la página;
Los ejemplos que se dan a continuación son bastante largos debido a que se ilustran lo que se produce cuando hay un fragmento de texto en las celdas de una tabla. Así, en lugar de reproducirlo en la página, id a [http://www.andy-roberts.net/misc/latex/latextutorial4.html] para poder consultar directamente el fichero {{LaTeX}} de ejemplo [https://www.andy-roberts.net/res/writing/latex/wrapped.tex wrapped.tex] y luego mirar el [https://www.andy-roberts.net/res/writing/latex/wrapped.pdf resultado].
== El entorno <code>tabular*</code>, control de la anchura de una tabla ==
Es fundamental una pequeña extensión de la versión básica de la tabla, ya que exige un parámetro suplementario (antes de las descripciones de columnas) para indicar la anchura deseada para la tabla.
\begin{tabular*}{0.75\textwidth}{ | c | c | c | r | }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabular*}
Sin embargo, esto no se parace a lo que se espera. Las columnas tienen siempre su anchura normal (justo lo suficientemente larga para adaptar su contenido mientras que las líneas son tan anchas como la anchura deseada de la tabla)
La tabla no tiene una buena apariencia. La razón de este desorden es debido a que se tiene que insertar un espacio suplementario en la columna. {{LaTeX}}, tiene una longitud en caucho, que a diferencia de otras, no son fijas y {{LaTeX}} puede dinámicamente decidir el momento en el que deben ser fijas. Así, la solución al problema propuesto es:
\begin{tabular*}{0.75\textwidth}{@{\extracolsep{\fill}} | c | c | c | r | }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabular*}
En el código se utiliza la construcción @{...} que se coloca al principio de la columna. Mas tarde se darán los detalles de este elemento. En el interior de estas construcciones, el comando <span class="command">\extracolsep</span>, exige una anchura como parámetro. Se habría podido utilizar una anchura fija, sin embargo, utilizando una longitud elástica, es decir, <span class="command">\fill</span>, las columnas se espacian automáticamente de manera uniforme.
{{AutoCat}}
iixph0cdfslwds5kqa96ex5himx1ln9
Manual de LaTeX/Escribiendo texto/Listas
0
23588
436539
292815
2026-10-15T07:47:15Z
Antimundo
74354
Categorizar usando AutoCat
436539
wikitext
text/x-wiki
'''12.1. LISTAS NO NUMERADAS'''
Este tipo de listas son simplemente un conjunto de elementos como el siguiente:
* leche
* pan y cereales
* legumbres
Una lista de este tipo se consigue con el entorno '''itemize''', donde cada elemento a especificar irá precedido del comando '''\item''', de la siguiente manera:
\begin{itemize}
\item leche
\item pan y cereales
\item legumbres
\end {itemize}
Este tipo de listas pueden anidarse. LATEX se encarga de la gestión de la apariencia de los distintos niveles de profundidad:
\begin{itemize}
\item leche
\item pan y cereales
*leche \begin{itemize}
*pan y cereales \item trigo
.trigo \begin{itemize}
º harina \item harina
\end {itemize}
.cebada \item cebada
.centeno \item centeno
.maiz \item maiz
\end{itemize}
*legumbres \item legumbres
.lentejas \begin{itemize}
\item lentejas
.garbanzos \item garbanzos
\end{itemize}
\end{itemize}
{{AutoCat}}
a2bpw0kccc23kwf7udrbmwbga3dli18
Wikilibros:Tablón de anuncios a los bibliotecarios
4
24997
436527
435252
2026-10-14T23:57:48Z
Mazbel
57931
/* Aviso de spam */ archive to [[Wikilibros:Tablón de anuncios a los bibliotecarios/Archivos/2026#Aviso de spam]] ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
436527
wikitext
text/x-wiki
{{/Cabecera}}
{{Usuario:MABot/config
|archive = Wikilibros:Tablón de anuncios a los bibliotecarios/Archivos/%(year)d
|algo = old(60d)
|counter = 1
|archiveheader = {{Archivo}}
|minthreadstoarchive = 1
|minthreadsleft = 0
}}<!-- SOLICITUDES DEBAJO, GRACIAS -->
<!-- recuerda, esta página sirve para denunciar a usuarios que EN ESTE MOMENTO vandalizan páginas -->
== Aviso de spam ==
Buenas. Vengo a avisar de esta cuenta que recientemente ha estado realizando vandalismos: [[Especial:Contribuciones/~2026-49864-76]]. Saludos. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 13:49 15 sep 2026 (UTC)
: Gracias por el aviso. Usuario bloqueado. [[Usuario:Mazbel|<span style="font-weight:bold; font-family:cursive, serif;">Mazbel</span>]] [[Usuario discusión:Mazbel|<span style="font-size:small; font-family:cursive, serif;">(Discusión)</span>]] 14:37 15 sep 2026 (UTC)
== Saludos y presentación ==
Saludos, como bien sabréis, tras la última votación, al final he salido elegido bibliotecario. Quería dejar este mensaje para comunicar que quedo a vuestra disposición si cometo algún error o hay cualquier asunto que queráis comentarme.
Como ya mencioné, al principio a menos que sean casos flagrante obvios, probablemente seguiré marcando muchas páginas para «borrado» en vez de borrarlas yo directamente hasta que vaya adquiriendo más experiencia. Creo que esto es más prudente pues hace que Mazbel o algún otro biblio con más experiencia que yo pueda revisar las páginas que marco para borrar. Cuando vaya adquiriendo más experiencia espero ir trabajando de forma más autónoma para no haceros perder el tiempo.
Algunas acciones que me vais a ver realizando próximamente serán simplemente hacer algunas correcciones de errores de sintaxis, como me habéis visto hacer últimamente, arreglar algunas páginas que están mal nombradas y, quizás revisar el nivel de protección de algunas páginas que quizás están excesivamente protegidas.
Dicho esto quedo a vuestra entera disposición, tengo los oídos abiertos para escuchar cualquier comentario. Si cometo algún error en algún momento, sabed que es por novato, pues edito siempre con buena fe y con ganas de mejorar este sitio.
Saludo a @[[Usuario:Ezarate|Ezarate]] y @[[Usuario:Mazbel|Mazbel]] para que se os notifique este mensaje pues sois los biblios que han sido activos últimamente. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 11:54 22 sep 2026 (UTC)
:::Eso, despacio vas a ir adquiriendo experiencia, disfruta de tus nuevos permisos! --[[Usuario:Ezarate|Esteban]] ([[Usuario discusión:Ezarate|discusión]]) 13:12 22 sep 2026 (UTC)
== Duda sobre inactividad de bibliotecarios ==
Buenos días. Estaba revisando, y según nuestra política de [[Wikilibros:Bibliotecarios#Inactividad]] tenemos dos usuarios bibliotecarios que actualmente llevan dos años sin realizar ninguna edición. No sé cómo se debe proceder en estos casos pero aviso para que estéis informados. Menciono a @[[Usuario:Ezarate|Ezarate]] y @[[Usuario:Mazbel|Mazbel]] por haber sido los otros biblios que habéis tenido actividad más recientemente y que seguramente sabréis mejor que yo qué hacer. ¡Un saludo! [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 11:21 30 sep 2026 (UTC)
::Para la próxima, [https://meta.wikimedia.org/w/index.php?title=Steward_requests/Permissions&diff=prev&oldid=31102811|seguí este ejemplo] --[[Usuario:Ezarate|Esteban]] ([[Usuario discusión:Ezarate|discusión]]) 12:35 30 sep 2026 (UTC)
1h8a68nta1tju6s8hyrthn5o47hnjz7
436529
436527
2026-10-14T23:57:59Z
Mazbel
57931
/* Aviso de spam */ archive to [[Wikilibros:Tablón de anuncios a los bibliotecarios/Archivos/2026#Aviso de spam]] ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
436529
wikitext
text/x-wiki
{{/Cabecera}}
{{Usuario:MABot/config
|archive = Wikilibros:Tablón de anuncios a los bibliotecarios/Archivos/%(year)d
|algo = old(60d)
|counter = 1
|archiveheader = {{Archivo}}
|minthreadstoarchive = 1
|minthreadsleft = 0
}}<!-- SOLICITUDES DEBAJO, GRACIAS -->
<!-- recuerda, esta página sirve para denunciar a usuarios que EN ESTE MOMENTO vandalizan páginas -->
== Saludos y presentación ==
Saludos, como bien sabréis, tras la última votación, al final he salido elegido bibliotecario. Quería dejar este mensaje para comunicar que quedo a vuestra disposición si cometo algún error o hay cualquier asunto que queráis comentarme.
Como ya mencioné, al principio a menos que sean casos flagrante obvios, probablemente seguiré marcando muchas páginas para «borrado» en vez de borrarlas yo directamente hasta que vaya adquiriendo más experiencia. Creo que esto es más prudente pues hace que Mazbel o algún otro biblio con más experiencia que yo pueda revisar las páginas que marco para borrar. Cuando vaya adquiriendo más experiencia espero ir trabajando de forma más autónoma para no haceros perder el tiempo.
Algunas acciones que me vais a ver realizando próximamente serán simplemente hacer algunas correcciones de errores de sintaxis, como me habéis visto hacer últimamente, arreglar algunas páginas que están mal nombradas y, quizás revisar el nivel de protección de algunas páginas que quizás están excesivamente protegidas.
Dicho esto quedo a vuestra entera disposición, tengo los oídos abiertos para escuchar cualquier comentario. Si cometo algún error en algún momento, sabed que es por novato, pues edito siempre con buena fe y con ganas de mejorar este sitio.
Saludo a @[[Usuario:Ezarate|Ezarate]] y @[[Usuario:Mazbel|Mazbel]] para que se os notifique este mensaje pues sois los biblios que han sido activos últimamente. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 11:54 22 sep 2026 (UTC)
:::Eso, despacio vas a ir adquiriendo experiencia, disfruta de tus nuevos permisos! --[[Usuario:Ezarate|Esteban]] ([[Usuario discusión:Ezarate|discusión]]) 13:12 22 sep 2026 (UTC)
== Duda sobre inactividad de bibliotecarios ==
Buenos días. Estaba revisando, y según nuestra política de [[Wikilibros:Bibliotecarios#Inactividad]] tenemos dos usuarios bibliotecarios que actualmente llevan dos años sin realizar ninguna edición. No sé cómo se debe proceder en estos casos pero aviso para que estéis informados. Menciono a @[[Usuario:Ezarate|Ezarate]] y @[[Usuario:Mazbel|Mazbel]] por haber sido los otros biblios que habéis tenido actividad más recientemente y que seguramente sabréis mejor que yo qué hacer. ¡Un saludo! [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 11:21 30 sep 2026 (UTC)
::Para la próxima, [https://meta.wikimedia.org/w/index.php?title=Steward_requests/Permissions&diff=prev&oldid=31102811|seguí este ejemplo] --[[Usuario:Ezarate|Esteban]] ([[Usuario discusión:Ezarate|discusión]]) 12:35 30 sep 2026 (UTC)
4ye8kd6900kf2hyx9j1jzngex3cbfp4
Plantilla:+ÍndiceSección
10
33860
436487
430922
2026-10-14T12:03:46Z
Luciérnaga de conocimiento
119502
436487
wikitext
text/x-wiki
<includeonly>__NOTOC__
{| {{+Tabla
|ancho = 250px
|alinear = right
|relleno = 10
|espaciado = 5
|estilo = border-radius:{{Variable|redondeo|{{{redondeo|}}}|1}}px; border:2px solid {{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}; background:{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}; margin: {{#ifeq:{{{posición|{{{1|}}}}}}|right|5px 0px 5px 10px|{{#ifeq:{{{posición|{{{1|}}}}}}|left|5px 17px 5px 0px|5px}}}}}}
|{{+Celda|0|110%|100%|center|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}2}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
'''Índice de la sección<br />«[[{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}|{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}]]»'''
|----
|{{+Celda|0|100%|100%|left|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|{{RGB|{{Variable|tono|{{{PAGENAME}}}|gris}}0}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
{{#ifeq:{{FULLPAGENAME}}|{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}||{{:{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}}}
|}
</includeonly><noinclude>{{documentación|Plantilla:+Índice/uso}}</noinclude>
j319xkib6gmgh78j2bt57bpgs0tswqy
436493
436487
2026-10-14T12:24:11Z
Luciérnaga de conocimiento
119502
436493
wikitext
text/x-wiki
<includeonly>__NOTOC__
{| {{+Tabla
|ancho = 250px
|alinear = right
|relleno = 10
|espaciado = 5
|estilo = border-radius:{{Variable|redondeo|{{{redondeo|}}}|1}}px; border:2px solid {{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}; background:{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}; margin: {{#ifeq:{{{posición|{{{1|}}}}}}|right|5px 0px 5px 10px|{{#ifeq:{{{posición|{{{1|}}}}}}|left|5px 17px 5px 0px|5px}}}}}}
|{{+Celda|0|110%|100%|center|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}2}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
'''Índice de la sección<br />«[[{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}|{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}]]»'''
|----
|{{+Celda|0|100%|100%|left|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|{{RGB|{{Variable|tono|{{{PAGENAME}}}|gris}}0}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
{{#ifeq:{{FULLPAGENAME}}|{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}||{{#ifeq:{{{libro|}}}|Haskell|
{{Capítulo de Haskell/Principios básicos de Haskell}}
|
{{:{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}
}}}}
|}
</includeonly><noinclude>{{documentación|Plantilla:+Índice/uso}}</noinclude>
h7lgd9utdfsfrp2k94ew7jtt9axpsi6
436499
436493
2026-10-14T12:36:49Z
Luciérnaga de conocimiento
119502
436499
wikitext
text/x-wiki
<includeonly>__NOTOC__
{| {{+Tabla
|ancho = 250px
|alinear = right
|relleno = 10
|espaciado = 5
|estilo = border-radius:{{Variable|redondeo|{{{redondeo|}}}|1}}px; border:2px solid {{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}; background:{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}; margin: {{#ifeq:{{{posición|{{{1|}}}}}}|right|5px 0px 5px 10px|{{#ifeq:{{{posición|{{{1|}}}}}}|left|5px 17px 5px 0px|5px}}}}}}
|{{+Celda|0|110%|100%|center|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}2}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
'''Índice de la sección<br />«[[{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}|{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}]]»'''
|----
|{{+Celda|0|100%|100%|left|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
{{#ifeq:{{{libro|}}}|Haskell|
{{Capítulo de Haskell/Principios básicos de Haskell}}
|
{{#ifeq:{{FULLPAGENAME}}|{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}||
{{:{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}
}}
}}
|}
</includeonly><noinclude>{{documentación|Plantilla:+Índice/uso}}</noinclude>
qimdpx8z55r9j46lefxpg0ph8onmsq4
436504
436499
2026-10-14T12:49:44Z
Luciérnaga de conocimiento
119502
436504
wikitext
text/x-wiki
<includeonly>__NOTOC__
{| {{+Tabla
|ancho = 250px
|alinear = right
|relleno = 10
|espaciado = 5
|estilo = border-radius:{{Variable|redondeo|{{{redondeo|}}}|1}}px; border:2px solid {{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}; background:{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}; margin: {{#ifeq:{{{posición|{{{1|}}}}}}|right|5px 0px 5px 10px|{{#ifeq:{{{posición|{{{1|}}}}}}|left|5px 17px 5px 0px|5px}}}}}}
|{{+Celda|0|110%|100%|center|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}2}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
'''Índice de la sección<br />«[[{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}|{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}]]»'''
|----
|{{+Celda|0|100%|100%|left|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
{{#if:{{{navegación|}}}|
{{{{{navegación}}}}}
|
{{#ifeq:{{FULLPAGENAME}}|{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}||
{{:{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}
}}
}}
|}
</includeonly><noinclude>{{documentación|Plantilla:+Índice/uso}}</noinclude>
n6avgykus6m636ky43brgypmrdh3lgs
436508
436504
2026-10-14T12:57:09Z
Luciérnaga de conocimiento
119502
436508
wikitext
text/x-wiki
<includeonly>__NOTOC__
{| {{+Tabla
|ancho = 250px
|alinear = right
|relleno = 10
|espaciado = 5
|estilo = border-radius:{{Variable|redondeo|{{{redondeo|}}}|1}}px; border:2px solid {{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}; background:{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}; margin: {{#ifeq:{{{posición|{{{1|}}}}}}|right|5px 0px 5px 10px|{{#ifeq:{{{posición|{{{1|}}}}}}|left|5px 17px 5px 0px|5px}}}}}}
|{{+Celda|0|110%|100%|center|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}9}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}2}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
'''Índice de la sección<br />«[[{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}|{{{título|{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}}]]»'''
|----
|{{+Celda|0|100%|100%|left|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|{{RGB|{{Variable|tono|{{{tono|}}}|gris}}0}}|middle|{{Variable|redondeo|{{{redondeo|}}}|1}}}}|
{{#if:{{{navegación|}}}|
{{{{{navegación}}}}}
|
{{#ifeq:{{FULLPAGENAME}}|{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}||
{{:{{{libro|{{#titleparts:{{PAGENAME}}|1}}}}}/{{{sección|{{#titleparts:{{PAGENAME}}|1|2}}}}}}}
}}
}}
|}
</includeonly><noinclude>{{documentación|Plantilla:+Índice/uso}}</noinclude>
33c4jw34krfszn6mjg8llnt0kdxrcxv
Wikilibros discusión:Escuela Virtual de Deportes
5
36047
436570
183648
2026-10-15T09:28:29Z
Antimundo
74354
Sección nueva: /* Retirar vinculaciones a la EVD */
436570
wikitext
text/x-wiki
El esfuerzo que representa hacer un libro sobre todos los deportes es descomunal e interesante y una de las cosas que mas trabajo nos dará será la de normalizar los términos usados en los deportes y luego cruzarlo con otros idiomas.
Primera sugerencia
Al Director del proyecto o cualquier otro que se sinta con la suficiente autoridad:
Hacer el Indice del Libro?, yo podría ayudar con eso.
Segunda.
En la primera clasicación de los deportes que encuentro colocas la etiquea de "deportes de lucha":
Antes de clasificar un deporte "de lucha" lo haria primero "de Contacto"; porque a los deportes que llamamos lucha (olimpica, greco-romana, libre, judo, etc.) sus técnicas no incluyen golpes.
== Retirar vinculaciones a la EVD ==
La Escuela Virtual del Deporte (EVD) fue una iniciativa del ''Ministerio del Deporte'' en Colombia para ofrecer formación sobre deportes a través de internet.
En el marco de dicha iniciativa, se incorporaron a Wikilibros numerosos materiales didácticos sobre distintas disciplinas deportivas, vinculándolos de manera generalizada con la identidad visual, la denominación y la imagen institucional del proyecto colombiano de la EVD.
Esta vinculación debe corregirse. Wikilibros es un proyecto colaborativo internacional e independiente, no una plataforma adscrita a ninguna institución gubernamental ni a ningún país. El uso generalizado de la denominación «Escuela Virtual del Deporte» y la presentación editorial de estos libros proyectan una identidad común que vincula indebidamente el contenido deportivo de Wikilibros con una iniciativa institucional colombiana.
En resumen. Estos libros sobre de deportes deberían ser simple y llanamente libros de deportes, y presentarse como tal. No como subproyectos con la línea editorial de una iniciativa de un ministerio de Colombia.
Menciono a @[[Usuario:Mazbel|Mazbel]] para conocer su opinión. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 09:28 15 oct 2026 (UTC)
49j12gw60pht60c0b4rnqo68ujx0m9a
Plantilla:AutoCat
10
38116
436518
427895
2026-10-14T13:17:26Z
Luciérnaga de conocimiento
119502
436518
wikitext
text/x-wiki
<includeonly>{{#switch:{{NAMESPACE}}
|{{TALKSPACE}}=
|Template={{#ifeq:{{{template-filing|}}}|deep
|[[Category:Libro:{{BOOKNAME}}/Templates{{#if:{{#titleparts:{{PAGENAME}}||3}}|/{{#titleparts:{{PAGENAME}}|-1|2}}}}|{{{1|{{#if:{{CHAPTERNAME}}|{{#titleparts:{{PAGENAME}}||-1}}}}}}}]][[Category:Pages with deep filing]]
|[[Category:Libro:{{BOOKNAME}}/Templates|{{{1|{{#titleparts:{{FULLPAGENAME}}||2}}}}}]]
}}
|Category={{#ifeq:{{FULLCHAPTERNAME}}|{{FULLBOOKNAME}}
|
|[[Category:{{#titleparts:{{PAGENAME}}|-1}}|{{{1|{{#titleparts:{{PAGENAME}}||-1}}}}}]]
{{#ifeq:{{FULLCHAPTERNAME}}|Templates
|[[Category:Book-specific templates|{{{1|{{PAGENAME}}}}}]]
}}
}}
|#default={{#ifeq:{{{filing|}}}|deep
|[[Category:Libro:{{#if:{{CHAPTERNAME}}|{{#titleparts:{{FULLPAGENAME}}|-1}}|{{FULLPAGENAME}}}}|{{{1|{{#if:{{CHAPTERNAME}}|{{#titleparts:{{PAGENAME}}||-1}}}}}}}]][[Category:Pages with deep filing]]
|[[Category:Libro:{{FULLBOOKNAME}}|{{{1|{{#titleparts:{{FULLPAGENAME}}||2}}}}}]]
}}
}}</includeonly><noinclude>
{{documentación}}
</noinclude>
eroyhoka55huu60jjm2cb569ry6t16q
Categoría:Libro:Manual de LaTeX
14
39384
436567
215147
2026-10-15T07:52:54Z
Antimundo
74354
Antimundo trasladó la página [[Categoría:Manual de LaTeX]] a [[Categoría:Libro:Manual de LaTeX]]: Política de nombrado
215147
wikitext
text/x-wiki
{{LP|Manual de LaTeX}}
[[Categoría:Programación|Latex]]
236gbvekmi77igg4ulaagz5dzvnl3kw
436569
436567
2026-10-15T09:01:49Z
Antimundo
74354
Categorizar usando estantes
436569
wikitext
text/x-wiki
{{LP|Manual de LaTeX}}
[[Categoría:Estante:Lenguajes de programación]]
8riajf7lcazry8az92304tjqpefq2sv
Manual de LaTeX/Índice
0
39388
436563
319854
2026-10-15T07:51:20Z
Antimundo
74354
Categorizar usando AutoCat
436563
wikitext
text/x-wiki
# '''<big>[[Manual de LaTeX/Datos preliminares|Introducción]]</big>'''
## [[Manual de LaTeX/Datos preliminares/Introducción a LaTeX|Introducción a LaTeX.]]
## [[Manual de LaTeX/Datos preliminares/La escritura en LaTeX|La escritura en LaTeX.]]
## [[Manual de LaTeX/Datos preliminares/Programas complementarios|Programas complementarios.]]
## [[Manual de LaTeX/Datos preliminares/Instalación en Linux|Instalación en Linux.]]
## [[Manual de LaTeX/Datos preliminares/Instalación en MS Windows|Instalación en MS Windows.]]
## [[Manual de LaTeX/Datos preliminares/Instalación en OS X|Instalación en MAC OS X.]]
# '''<big>[[Manual de LaTeX/La estructura de un documento en LaTeX|La estructura de un documento en LaTeX]]</big>'''
## [[Manual de LaTeX/La estructura de un documento en LaTeX/El preámbulo y el cuerpo del documento|El preámbulo y el cuerpo del documento.]]
## [[Manual de LaTeX/La estructura de un documento en LaTeX/Clases de documento y algunos paquetes comunes|Clases de documento y algunos paquetes comunes.]]
# '''<big>[[Manual de LaTeX/Escribiendo texto|Escribiendo texto]]</big>'''
## [[Manual de LaTeX/Escribiendo texto/Espacios|Espacios.]]
## [[Manual de LaTeX/Escribiendo texto/Caracteres especiales|Caracteres especiales.]]
## [[Manual de LaTeX/Escribiendo texto/Tamaños, estilos y tipos de letra|Tamaños, estilos y tipos de letra.]]
## [[Manual de LaTeX/Escribiendo texto/Alineación del texto|Alineación del texto.]]
## [[Manual de LaTeX/Escribiendo texto/Partición de palabras|Partición de palabras.]]
## [[Manual de LaTeX/Escribiendo texto/Signos ortográficos|Signos ortográficos.]]
## [[Manual de LaTeX/Escribiendo texto/Portada del documento|Portada del documento.]]
## [[Manual de LaTeX/Escribiendo texto/Capítulos y secciones|Capítulos y secciones.]]
## [[Manual de LaTeX/Escribiendo texto/Estilos de página|Estilos de página.]]
## [[Manual de LaTeX/Escribiendo texto/Referencias|Referencias.]]
## [[Manual de LaTeX/Escribiendo texto/Notas al pie|Notas al pie.]]
## [[Manual de LaTeX/Escribiendo texto/Listas|Listas.]]
## [[Manual de LaTeX/Escribiendo texto/Citas|Citas.]]
## [[Manual de LaTeX/Escribiendo texto/Tablas|Tablas.]]
# '''<big>[[Manual de LaTeX/Fórmulas matemáticas|Fórmulas matemáticas]]</big>'''
## [[Manual de LaTeX/Fórmulas matemáticas/Inserción de fórmulas|Inserción de fórmulas.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Superíndices y subíndices|Superíndices y subíndices.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Construcciones matemáticas|Construcciones matemáticas.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Delimitadores|Delimitadores.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Símbolos matemáticos|Símbolos matemáticos.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Puntuación|Puntuación.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Acentuación en modo matemático|Acentuación en modo matemático.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Texto entre matemáticas|Texto entre matemáticas.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Arreglos matemáticos|Arreglos matemáticos.]]
## [[Manual de LaTeX/Fórmulas matemáticas/Entornos para teoremas|Entornos para teoremas.]]
# '''<big>[[Manual de LaTeX/Gráficos|Gráficos]]</big>'''
## [[Manual de LaTeX/Gráficos/Objetos flotantes|Objetos flotantes.]]
## [[Manual de LaTeX/Gráficos/Ubicación de un gráfico|Ubicación de un gráfico.]]
## [[Manual de LaTeX/Gráficos/Inclusión de gráficos EPS|Inclusión de gráficos EPS.]]
## [[Manual de LaTeX/Gráficos/Conversión de formatos gráficos|Conversión de formatos gráficos.]]
## [[Manual de LaTeX/Gráficos/Dibujo de gráficos en LaTeX|Dibujo de gráficos en LaTeX.]]
## [[Manual de LaTeX/Gráficos/El paquete XY-Pic|El paquete XY-Pic.]]
## [[Manual de LaTeX/Gráficos/Gráficos con PSTricks|Gráficos con PSTricks.]]
## [[Manual de LaTeX/Gráficos/Gráficos con METAPOST|Gráficos con METAPOST.]]
## [[Manual de LaTeX/Gráficos/Gráficos con xfig|Gráficos con xfig.]]
## [[Manual de LaTeX/Gráficos/Gráficos con Tikz|Gráficos con Tikz.]]
# '''<big>[[Manual de LaTeX/Listados de código|Listados de código]]</big>'''
{{AutoCat}}
sqfrz48l780ocd9n9pivygzmyvo7id1
Manual de LaTeX/La estructura de un documento en LaTeX/Preámbulo/Paquetes comunes
0
39399
436560
385190
2026-10-15T07:50:36Z
Antimundo
74354
Categorizar usando AutoCat
436560
wikitext
text/x-wiki
{{navegar
|libro=Manual de LaTeX
|reducido=
|actual=La estructura de un documento en LaTeX/Preámbulo/Paquetes comunes
|anterior=La estructura de un documento en LaTeX/Preámbulo/Clases de documento
|siguiente=
}}
Además de las clases estándar de documento de {{LaTeX}} descritas en el apartado anterior, hay algunos paquetes que normalmente vienen incluidos en cualquier distribución de {{LaTeX}} (más específicamente, en distribuciones de {{LaTeX|2e}}). Algunos de ellos los describiremos más detalladamente en capítulos posteriores, y nos limitaremos a dar aquí una tabla que los compendie:
{|{{Tablabonita}}
|valign="top" width="75px"| '''alltt'''
|valign="top" | Este paquete provee el entorno <syntaxhighlight lang="latex" enclose="none">alltt</syntaxhighlight>, muy similar al entorno <syntaxhighlight lang="latex" enclose="none">verbatim</syntaxhighlight> salvo que "<syntaxhighlight lang="latex" enclose="none">\</syntaxhighlight>", "<syntaxhighlight lang="latex" enclose="none">{</syntaxhighlight>" y "<syntaxhighlight lang="latex" enclose="none">} </syntaxhighlight>" tienen su significado usual, por lo que pueden ser introducidos comandos.
|-
|valign="top" | '''doc'''
|Este es un paquete básico para la escritura de documentación de programas de {{LaTeX}}.
|-
|valign="top" | '''excale'''
|Este paquete proporciona versiones escaladas de las fuentes matemáticas de extensión.
|-
|valign="top" | '''fontenc'''
|Este paquete se usa para especificar la codificación de fuente que debe usar {{LaTeX}}
|-
|valign="top" | '''graphpap'''
|Este comando permite el uso del comando <syntaxhighlight lang="latex" enclose="none">\graphpaper</syntaxhighlight>, que se usa para dibujar cuadriculados o mallas.
|-
|valign="top" | '''ifthen'''
|Para comandos de la forma if... then... else...
|-
|valign="top" | '''inputenc'''
|Este paquete se usa para especificar la codificación de caracteres para los documentos de entrada de {{LaTeX}}. Si vamos a escribir en español, conviene usar la instrucción <syntaxhighlight lang="latex" enclose="none">\usepackage[latin1]{inputenc} </syntaxhighlight><ref>En algunas distribuciones es mejor escribir: <syntaxhighlight lang="latex">\usepackage[utf8]{inputenc}</syntaxhighlight></ref>, que nos permitirá escribir con acentos en nuestro archivo de entrada, y con ello no tendremos que escribir cosas como <syntaxhighlight lang="latex" enclose="none">pr\'actico</syntaxhighlight> para obtener "práctico" en nuestro documento compilado. Lo mismo sucede con la tilde que lleva la eñe.
|-
|valign="top" | '''latexsym'''
|Puesto que en {{LaTeX|2e}} los caracteres símbolos ya no son cargados automáticamente, es necesario cargar el paquete <syntaxhighlight lang="latex" enclose="none">latexsym</syntaxhighlight> para poder disponer de ellos.
|-
|valign="top" | '''makeidx'''
|Este paquete proporciona comandos para la construcción de índices alfabético.
|-
|valign="top" | '''syntonly'''
|Este paquete causará que el documento sea procesado sin producir ningún documento compilado de salida, sino que lo único que nos permitirá hacer es verificar que la sintaxis de cada comando es correcta.
|}
No obstante, los paquetes de la tabla anterior cumplen propósitos muy específicos y es probable que el lector no tenga interés en todos ellos. Existen paquetes muy comunes que son de gran utilidad:
{|{{Tablabonita}}
|valign="top" width="75px"| '''amsmath'''
|valign="top" | Este paquete, realizado por la American Mathematical Society, proporciona comandos para la escritura de fórmulas matemáticas de mayor complejidad.
|-
|valign="top" | '''babel'''
|Este paquete esta hecho para soportar lenguajes diversos, entre ellos el español. Para indicar que nuestro documento se escribirá en español, y con ello que éste se adapte a dicho idioma, hemos de escribir <syntaxhighlight lang="latex" enclose="none">usepackage[spanish]{babel} </syntaxhighlight>.
|-
|valign="top" | '''graphics'''
|Con este paquete podrás incluir y transformar imágenes en tu documento, incluyendo las que hayas creado con otros programas.
|}
== Marcas de agua: {{Verb|draftwatermarks}} ==
El paquete {{Verb|draftwatermarks}}<ref>[http://mirrors.ctan.org/macros/latex/contrib/draftwatermark/draftwatermark.pdf Documentación del paquete {{Verb|draftwatermark}} en CTAN]</ref> permite introducir en los documentos marcas de agua, importa automáticamente el paquete {{Verb|color}}. Para usarlo en un documento {{LaTeX}} basta con importar en el preámbulo el paquete:
<syntaxhighlight lang="latex">\usepackage{draftwatermarks}</syntaxhighlight>
=== Modo de uso ===
Con sólo importar el paquete, se introducirá la marca de agua por defecto, consistente en el texto "DRAFT", en gris al 80% con un tamaño de fuente de 5 cm y un factor de escala de 1'2, con un ángulo de inclinación de 45º. Para modificar cualquiera de estas cinco propiedades se emplean las siguientes instrucciones:
* Para el texto: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkText{NuevoTexto}</syntaxhighlight>
* Para un tono de gris: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkColor[gray]{0.5}</syntaxhighlight>, con el rango [0,1].
* Para un color diferente: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkColor[rgb]{1,0,0}</syntaxhighlight>, con el rango [0,1] para cada color primario.
* Para el tamaño de la fuente: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkFontSize{3cm}</syntaxhighlight>
* Para el factor de escala: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkScale{5}</syntaxhighlight>
* Para el ángulo de inclinación: <syntaxhighlight lang="latex" enclose="none">\SetWatermarkAngle{30}</syntaxhighlight>, en grados.
== Referencias ==
{{listaref}}
{{Notapie}}
{{AutoCat}}
5qo60hvctwhcsldi39mchkjhsdu299z
Manual de LaTeX/Programación en LaTeX
0
39400
436561
215267
2026-10-15T07:50:44Z
Antimundo
74354
Categorizar usando AutoCat
436561
wikitext
text/x-wiki
programación en {{LaTeX}}
{{AutoCat}}
h2w7vp856j2gp7r5l1htupewnu27hzx
436562
436561
2026-10-15T07:51:01Z
Antimundo
74354
436562
wikitext
text/x-wiki
Programación en {{LaTeX}}
{{AutoCat}}
8al9in18ic4bbaplp1l5u2d2n25scze
Manual de LaTeX/Escribiendo texto/Referencias
0
39405
436541
292153
2026-10-15T07:47:36Z
Antimundo
74354
Categorizar usando AutoCat
436541
wikitext
text/x-wiki
Para las remisiones internas de un documento, llamadas a veces referencias cruzadas (del inglés ''cross references'') podemos usar los comandos
<source lang="latex" enclose="none">\label{''etiqueta''}</source>
<source lang="latex" enclose="none">\ref{''etiqueta''}</source>
<source lang="latex" enclose="none">\pageref{''etiqueta''}</source>
para hacer referencias del tipo “en la sección 2.2 hemos visto que...” Por ejemplo, si tenemos en el documento un capítulo indicado con <source lang="latex" enclose="none">\section{Métodos básicos}</source>, podemos etiquetarlo con <source lang="latex" enclose="none">\label{}</source> de la siguiente manera:
<center><source lang="latex">\section{Métodos básicos}\label{cap:MetBas}</source></center>
Con esto podremos referirnos a tal capítulo en cualquier momento mediante <source lang="latex" enclose="none">\ref{cap:MetBas}</source>.
{{Notas|contenido=Debemos señalar que para lograr referencias satisfactoriamente es necesario compilar el documento dos veces. Lo que sucede es que con la primera compilación los datos de referencia son guardados, y después, con una segunda compilación, obtendremos las referencias de manera adecuada en el documento. Por otra parte, si hacemos referencia a una etiqueta que no hemos indicado, tendremos un mensaje de error en el proceso de compilación, y el comando <source lang="latex" enclose="none">\ref{''etiqueta equivocada''}</source> será sustituido en el documento compilado por un par de signos de interrogación, ??.}}
Si queremos también incluir la página en la que aparece el capítulo, escribimos <source lang="latex" enclose="none">\pageref{cap:MetBas}</source>. Más aún, podemos definir el comando
<source lang="latex" enclose="none">\newcommand{\fullref}[1]{\ref{#1} de la página \pageref{#1}}</source>
de tal modo que si el capítulo “Métodos básicos” (etiquetado como antes) es el número 7 y se encuentra en la página 205, al escribir
<source lang="latex" enclose="none">... en el capítulo \fullref{cap:MetBas}, hemos tratado el tema de...</source>
obtenemos ... en el capítulo 7 de la página 205, hemos tratado el tema de...
Sin embargo, puede darse el caso de que <source lang="latex" enclose="none">\label{}</source> y nuestro nuevo comando, <source lang="latex" enclose="none">\fullref{}</source>, queden en la misma página, caso en el cual <source lang="latex" enclose="none">\fillref{}</source> producirá un resultado no deseable (indicaciones como “en la página x...” cuando es la misma página “x” en la que nos encontramos). Si observamos, en el texto compilado, que eso sucede, podemos usar simplemente <source lang="latex" enclose="none">\ref{}</source> en lugar del comando <source lang="latex" enclose="none">\fullref{}</source> que hemos definido.
Aún mejor puede resultar el uso del paquete <source lang="latex" enclose="none">varioref</source>, que nos provee de los comandos <source lang="latex" enclose="none">\vref{}</source>, <source lang="latex" enclose="none">\vpageref{}</source> y <source lang="latex" enclose="none">\vrefrange{}</source>. El comando <source lang="latex" enclose="none">\vref{}</source> es similar al comando <source lang="latex" enclose="none">\ref</source> salvo por que <source lang="latex" enclose="none">\vref</source> produce referencias del tipo “on the facing page” o “on page 205” siempre y cuando <source lang="latex" enclose="none">\label</source> no se encuentre en la misma página. Para adaptarlo al castellano hemos de indicar la opción <source lang="latex" enclose="none">spanish</source> al cargar el paquete, es decir, debemos escribir <source lang="latex" enclose="none">\usepackage[spanish]{varioref}</source>.
{{Notas|Aviso|contenido=Hay que tener cierto cuidado a la hora de usar el comando <source lang="latex" enclose="none">\vref</source>, pues hay ciertos errores que pueden suceder. Más exactamente, hay que evitar el uso de <source lang="latex" enclose="none">\vref</source> cuando las referencias del tipo “en esta página” se rompan en un cambio de página. Si esto sucede, veremos un error que nos permitirá ubicar el comando <source lang="latex" enclose="none">\vref</source> que deberá ser sustituido por un simple <source lang="latex" enclose="none">\ref</source>.}}
{{AutoCat}}
aqirdr0mbwy6jrseffxo4n3n3e7l80r
Manual de LaTeX/Info
0
39460
436532
215794
2026-10-15T07:44:51Z
Antimundo
74354
Categorizar usando AutoCat
436532
wikitext
text/x-wiki
Con este wikilibro se pretende desarrollar un manual de uso de LaTeX desde los conceptos básicos hasta los más avanzados, describiendo paso a paso todo lo necesario para producir documentos PDF de calidad. Se indicarán los paquetes necesarios para producir textos técnicos o introducir gráficos en los documentos.
{{AutoCat}}
nvghsrfzpqtwmpocx76dya3zeo0bfd4
Manual de LaTeX/Textos técnicos/Química/XyMTeX
0
39462
436564
385204
2026-10-15T07:51:26Z
Antimundo
74354
Categorizar usando AutoCat
436564
wikitext
text/x-wiki
El [http://www.ctan.org/pkg/xymtex paquete] {{XyMTeX}}, de Shinsaku Fujita, permite representar estructuras químicas en 2D. Permite trabajar con tres modos de compatibilidad según el proceso de compilado del documento que se vaya a emplear, a saber:
* Compatibilidad {{TeX}}/{{LaTeX}}, mediante el paquete {{Verb|xymtex}}.
* Compatibilidad PostScript, mediante el paquete {{Verb|}}.
* Compatibilidad PDF, mediante el paquete {{Verb|}}.
Es necesario incluir tres paquetes en el preámbulo del documento, aunque el primero dependerá del modo de compatibilidad escogido:
<syntaxhighlight lang="latex">
\usepackage{xymtex}
\usepackage{xcolor}
\usepackage{graphicx}
</syntaxhighlight>
<!-- ¿Paquete chemist? -->
== Uso básico ==
* yl-functions
* Listas de substitución {{Verb|<subslist>}}.
* Listas atómicas {{Verb|<atomlist>}}.
* Listas ligadas {{Verb|<bondlist>}}.
* Listas ligadas esqueléticas {{Verb|<skelbdlist>}}.
* Listas ligadas eliminadas {{Verb|<delbdlist>}}.
* Fusionando unidades
* Reduciendo el tamaño
== Compuestos alifáticos ==
* Compuestos planares
* Compuestos no planares
* Cadenas en zigzag
== Carbociclos ==
* Carbociclos de 6 miembros
* Carbociclos de menos de 6 miembros
* Carbociclos fusionados
* Otros carbociclos
== Heterociclos ==
* Heterociclos de 6 miembros
* Heterociclos de menos de 6 miembros
* Heterociclos fusionados
* Otros heterociclos
== Técnicas avanzadas ==
* Polímeros
* Combinación de estructuras
* Estereoquímica
* Fórmulas moleculares
* Reacciones químicas
* Coloreado
* Generación de archivos EPS
* Generación de archivos PDF
== Referencias ==
* [http://www.ctan.org/pkg/xymtex Paquete XyMTeX en CTAN]
* [http://xymtex.com/fujitas3/xymtex/xym501/manual/xymtex-manualPS.pdf Manual de XyMTeX]
* [http://xymtex.com/fujitas/fujitae.html Web del creador]
{{AutoCat}}
bis0muugzgcf8ynrdt2ih2u43ghizh3
Manual de LaTeX/Textos técnicos/Química/chemfig
0
39483
436565
378152
2026-10-15T07:51:34Z
Antimundo
74354
Categorizar usando AutoCat
436565
wikitext
text/x-wiki
El paquete [http://www.ctan.org/tex-archive/macros/latex/contrib/chemfig/ chemfig] permite realizar representaciones en 2D de estructuras químicas, usa el paquete gráfico [http://www.ctan.org/pkg/pgf PGF (TkiZ)]. Es necesario incluirlo en el preámbulo para poder usarlo.
<syntaxhighlight lang="latex">
\usepackage{chemfig}
</syntaxhighlight>
== Uso básico ==
La sintaxis básica para representar estructuras químicas con este paquete es:
<syntaxhighlight lang="latex">
\chemfig{<Atomo1><TipoEnlace>[<Angulo>,<Factor>,<CodTikZ>]<Atomo2>}
</syntaxhighlight>
=== Tipo de enlaces: <code><TipoEnlace></code> ===
Permite definir el tipo de enlace entre las siguientes nueve posibilidades:
{{LaTeX/Ejemplo
|code=\chemfig{A-B}
\chemfig{A=B}
\chemfig{A~B}
\chemfig{A>B}
\chemfig{A<B}
\chemfig{A>:B}
\chemfig{A<:B}
\chemfig{A>{{!}}B}
\chemfig{A<{{!}}B}
|render=[[Image:Chemfig_bonds.png|100px]]}}
=== Ángulos de enlaces: <code><Angulo></code> ===
Se puede definir el ángulo del enlace entre dos átomos con tres medidas diferentes:
# ''Predefinidas'': dividen la circunferencia en 8 intervalos de 45 grados, se indican con un número entre 0 y 7 ({{Verb|<Angulo>}}).
# ''Absolutas'': se indica el ángulo exacto en grados (de -360 a 360) precedido de dos puntos ({{Verb|:<Angulo>}}).
# ''Relativas'': van referidos al ángulo del último enlace definido, se indica en grados precedido de doble dos puntos ({{Verb|::<Angulo>}}).
{{LaTeX/Ejemplo
|code=\chemfig{(-[:0,1.5,,,draw=none]\scriptstyle\color{red}0)
(-[1]1)(-[:45,1.5,,,draw=none]\scriptstyle\color{red}45)
(-[2]2)(-[:90,1.5,,,draw=none]\scriptstyle\color{red}90)
(-[3]3)(-[:135,1.5,,,draw=none]\scriptstyle\color{red}135)
(-[4]4)(-[:180,1.5,,,draw=none]\scriptstyle\color{red}180)
(-[5]5)(-[:225,1.5,,,draw=none]\scriptstyle\color{red}225)
(-[6]6)(-[:270,1.5,,,draw=none]\scriptstyle\color{red}270)
(-[7]7)(-[:315,1.5,,,draw=none]\scriptstyle\color{red}315)
-0}
|render=[[Image:Chemfig_angles.png|250px]]}}
=== Factor de escala: <code><Factor></code> ===
Permite introducir un factor de escala para el enlace.
=== Código TikZ: <code><CodTkiZ></code> ===
Permite introducir opciones adicionales para modificar el color o el estilo del enlace.
== Fórmulas esqueléticas ==
Para compuestos alifáticos es suficiente con concatenar los átomos indicando el tipo de enlace. Por ejemplo:
{{LaTeX/Ejemplo
|code=\chemfig{-[:30]=[:-30]-[:30]}
|render=[[Image:Skeletondiagram2.png|160px]]}}
Para anillos hay que usar la sintaxis:
<syntaxhighlight lang="latex">
\chemfig{<Atomo1>*<num>(<TipoEnlace><AtomoN2>)}
</syntaxhighlight>
{{LaTeX/Ejemplo
|code=\chemfig{A*6(-B-C-D-E-F-)}
|render=[[Image:Ring_chemfig.png|120px]]}}
Para más información, véase: [http://osl.ugr.es/CTAN/macros/latex/contrib/chemfig/chemfig_doc_en.pdf Manual de chemfig].
{{AutoCat}}
eug2x5ge5kma6rxd66a2fieq0k0f4qg
Plantilla:Capítulo de Haskell/Principios básicos de Haskell
10
61798
436489
436142
2026-10-14T12:17:12Z
Luciérnaga de conocimiento
119502
436489
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Preparaciones|Preparaciones]]
{{{sep|<br>}}}[[Haskell/Variables y funciones|Variables y funciones]]
{{{sep|<br>}}}[[Haskell/Valores de verdad|Valores de verdad]]
{{{sep|<br>}}}[[Haskell/Tipos básicos|Tipos básicos]]
{{{sep|<br>}}}[[Haskell/Listas y tuplas|Listas y tuplas]]
{{{sep|<br>}}}[[Haskell/Tipos básicos II|Tipos básicos II]]
{{{sep|<br>}}}[[Haskell/Siguientes pasos|Siguientes pasos]]
{{{sep|<br>}}}[[Haskell/Construyendo vocabulario|Construyendo vocabulario]]
{{{sep|<br>}}}[[Haskell/Entrada y salida simple|Entrada y salida simple]]
[[Categoría:Haskell/Plantillas]]
c0kk1taub55b91bj1gy9c2x9mlnyyge
Haskell/Preparaciones
0
61814
436503
435962
2026-10-14T12:42:06Z
Luciérnaga de conocimiento
119502
436503
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Capítulo de Haskell/Principios básicos de Haskell}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
jvvxix2l2hvzi8df3e544obmu5p2shd
436510
436503
2026-10-14T12:59:28Z
Luciérnaga de conocimiento
119502
436510
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Preparaciones|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
0v4c7r73m5lhkgix9d0xb64t27837jf
436511
436510
2026-10-14T13:01:47Z
Luciérnaga de conocimiento
119502
436511
wikitext
text/x-wiki
{{+ÍndiceSección
|libro=Haskell
|sección=Preparaciones
|título=Capítulo de Haskell/Principios básicos de Haskell
|navegación=Capítulo de Haskell/Principios básicos de Haskell
}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
emay7wzjdos7mc18j7ljbour06kx5bf
436512
436511
2026-10-14T13:04:07Z
Luciérnaga de conocimiento
119502
436512
wikitext
text/x-wiki
{{+ÍndiceSección
|libro=Haskell
|sección=Preparaciones
|título=Principios básicos de Haskell
|navegación=Capítulo de Haskell/Principios básicos de Haskell
}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
m7qmguau5n7qu62lecur8mr9o5w5gn9
436514
436512
2026-10-14T13:07:04Z
Luciérnaga de conocimiento
119502
436514
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Variables y funciones|título=Principios básicos de Haskell|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
6q0otwwo5bnt597lvz97jyczlkji14b
436515
436514
2026-10-14T13:07:36Z
Luciérnaga de conocimiento
119502
436515
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Preparaciones|título=Principios básicos de Haskell|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
Este capítulo describe cómo instalar los programas que necesitarás para empezar a programar en Haskell.
== Instalando Haskell ==
Haskell es un ''lenguaje de programación'', es decir, un lenguaje en el que los seres humanos pueden expresar cómo deben trabajar las computadoras. Es como escribir una receta de cocina: escribes la receta y la computadora la ejecuta.
Para ejecutar programas en Haskell, necesitarás un programa especial llamado ''compilador''. Un compilador traduce el código escrito en Haskell a un ''código máquina'', un lenguaje más básico y elemental que la computadora todavía puede entender. De nuevo, escribes la receta (tu programa en Haskell) y un pastelero (el compilador) se encarga de mezclar los ingredientes para crear un pastel que realmente se pueda comer (un archivo ejecutable). Por supuesto, no es fácil recuperar la receta a partir del pastel terminado, del mismo modo que no es posible reconstruir el código Haskell a partir de un ejecutable ya compilado.
Para empezar, visita [http://www.haskell.org/downloads haskell.org/downloads] y sigue las instrucciones para instalar el «Glasgow Haskell Compiler» (GHC) y todo lo que necesites.
Si solo quieres hacer algunas pruebas básicas sin instalar nada, en [https://www.haskell.org/ Haskell.org] encontrarás una versión simplificada de un intérprete en la página principal. Las instrucciones de este libro suponen que tienes instalada la versión completa de GHC, aunque algunas cosas pueden funcionar en el sitio web.
{{Nota|1=
Para los usuarios de sistemas UNIX:
Si eres de los que prefieren compilar los programas en lugar de instalarlos ya preparados, quizá no sea buena idea hacerlo con GHC, sobre todo si es la primera vez que lo instalas. Esto se debe a que gran parte de GHC está escrita en Haskell, por lo que compilarlo puede resultar bastante laborioso. Además, puede llevar ''muchísimo'' tiempo y consumir mucho espacio en disco. Si aun así quieres continuar, visita [http://hackage.haskell.org/trac/ghc/wiki/Building Building and Porting GHC en la página de GHC].
}}
== Primer código ==
Una vez instalado todo, probaremos nuestros primeros programas con una herramienta llamada '''GHCi''' (la «i» significa «interactivo»). Según tu sistema operativo, haz lo siguiente:
Windows: ve al menú Inicio, luego selecciona «Ejecutar…» e introduce «cmd». Cuando se abra la nueva ventana, escribe el comando <code>ghci</code>.
MacOS: abre la aplicación «Terminal» e introduce el comando <code>ghci</code> en la nueva ventana que aparecerá.
Linux: abre una terminal y ejecuta <code>ghci</code>.
Probablemente verás algo parecido a esto:
<pre>
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
</pre>
La primera línea muestra la versión de GHCi. A continuación, se indica que se está cargando el paquete base para que tengas acceso a la mayoría de las funciones nativas y los módulos que vienen con GHC. Por último, <code>Prelude></code> indica que GHCi está listo para recibir comandos.
Primero, veamos la aritmética básica:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
Estos operadores son los mismos que se utilizan en la mayoría de los demás lenguajes de programación: <code>+</code> es la suma, <code>*</code> es la multiplicación y <code>^</code> es la potenciación (elevar a una potencia, o <math>a ^ b</math>). Como muestra el segundo ejemplo, Haskell sigue el orden habitual de las operaciones matemáticas; es decir, la multiplicación se realiza antes que la suma.
Ahora ya sabes cómo usar Haskell como calculadora. En realidad, Haskell ''siempre'' será una calculadora, solo que muy poderosa, capaz de trabajar no solo con números, sino también con otros objetos, como caracteres, listas, funciones, árboles e incluso programas enteros (si no conoces estos términos, no te preocupes).
Para salir de GHCi, escribe <code></code> (o simplemente <code></code>):
{{Haskell/GHCi|
Prelude>
Leaving GHCi.
}}
GHCi es un entorno de desarrollo bastante poderoso. A medida que avancemos, aprenderás a cargar archivos de código fuente en GHCi y a ejecutar distintas partes de ellos.
Si has entendido todo hasta aquí, ya estás listo para pasar al siguiente capítulo, en el que introduciremos algunos conceptos básicos de Haskell y escribiremos nuestra primera función.
{{AutoCat}}
grpz75vzzgh6xdfg1xhag76vmk8ko9f
Wikilibros:Tablón de anuncios a los bibliotecarios/Archivos/2026
4
64024
436526
432403
2026-10-14T23:57:47Z
Mazbel
57931
/* Aviso de spam */ archive from [[Wikilibros:Tablón de anuncios a los bibliotecarios]] ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
436526
wikitext
text/x-wiki
{{Archivo}}
== Cambios en el manual y petición de eliminar unas páginas ==
Muy buenas, escribo este post para explicar un asunto en el que estoy trabajando ¡pillad una tacita de té que me ha quedado un poco largo!
Hasta ahora ha existido una duplicidad entre dos páginas:
* «''El uso de Wikilibros''»: Un esbozo de la traducción de la versión en inglés «''The use of Wikibooks''» creado en 2015 pero que nunca se llegó a empezar a escribir realmente.
* «''Wikilibros:Manual''»: Un libro que tan solo contiene 7 páginas muy escuetas cuyo contenido no ha cambiado prácticamente nada desde que se creó en el año 2005.
Mi intención es unificar ambos en «''[[Manual de Wikilibros]]''», llevo unos días trabajando en completar este libro. {{archivar}}
=== Motivación ===
El motivo por el que creo que «''Wikilibros:Manual''» no es un nombre adecuado, es que este manual es un libro como cualquier otro, al igual que existe «''[[Manual wiki]]''» que es un libro acerca del entorno Wiki, «''Wikilibros:Manual''» es un libro acerca de Wikilibros, no una política oficial de este, y por lo tanto, no debería estar bajo el prefijo «''Wikilibros:''».
Además llamarlo simplemente «''Wikilibros:Manual''» es confuso, ya que se solapa por ejemplo con «''[[Wikilibros:Manual de estilo]]''» el cual sí es una política oficial, a diferencia de «''Wikilibros:Manual''» que es simplemente un manual de uso.
Personalmente todas estas cosas me generaron mucha confusión cuando llegué por primera vez a Wikilibros. Sumado a la confusión extra causada porque las páginas de Bienvenida y Ayuda eran a su vez tan solo una página en la que se encontraba una o varias páginas de «''Wikilibros:Manual''» transcluídas (lo cual estoy en proceso de cambiar y mejorar)... Me pareció que la experiencia de bienvenida a wikilibros era sumamente confusa, y por ello estoy trabajando en mejorar todo esto.
En resumen, al igual que se hace en las versiones de Wikilibros de otros idiomas (como el inglés), y como hacemos con el libro de «''Manual wiki''», veo mas limpio y claro que este manual esté alojado bajo «''Manual de Wikilibros''». Y que la página de Bienvenida y Ayuda no sean transclusiones del manual, si no que sean su propia página de bienvenida y ayuda como ocurre en Wikilibros en otros idiomas, o incluso en otras Wikipedias, incluída la Wikipedia en español.
=== ¿Qué pretendo hacer a continuación? ===
Mi intención es terminar de escribir «''[[Manual de Wikilibros]]''» (calculo que terminaré este fin de semana), después, haré que la páginas de Bienvenida no sea una transclusión de este manual, si no su propia página. Luego, actualizaré los enlaces que dirigen al viejo «''Wikilibros:Manual''» para que redireccionen al nuevo «''Manual de Wikilibros''». Y finalmente, cuando esté todo completado, solicitaré una fusión de historiales para fusionar «''Wikilibros:Manual''» en «''Manual de Wikilibros''».
: Al realizar la fusión de historiales, se crea una redirección automática, por lo que no será necesario que se actualicen los antiguos enlaces. [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 04:23 11 jun 2026 (UTC)
=== Petición de borrar algunas redirecciones ===
Debido a todo lo mencionado, una de mis acciones ha sido renombrar el libro «''El uso de Wikilibros''» a «''[[Manual de Wikilibros]]''», para darle un nombre mas claro y descriptivo que refleje mejor el propósito que he explicado.
Pero al trasladar este libro, se han creado muchos artículos con redirecciones que creo que deberían borrarse porque:
# No rompe ningún enlace: antes de que yo empezase a contribuir a este libro, este carecía de contenido, y por lo tanto no hay necesidad de que el «''El uso de Wikilibros''» sea una redirección, ya que no hay nada que redirigir. He buscado por buscadores web, y tampoco he encontrado nada que enlace a «''El uso de Wikilibros''».
# Teniendo en cuenta que no rompe ningún enlace, por simple limpieza, creo que lo mejor es simplemente borrar las páginas que listo abajo.
*{{L|El uso de Wikilibros}}
*{{L|El uso de Wikilibros/Acerca de este libro}}
*{{L|El uso de Wikilibros/Qué es Wikilibros}}
* {{L|El uso de Wikilibros/Crear una cuenta de usuario}}
*{{L|El uso de Wikilibros/Discusión y consenso}}
*{{L|El uso de Wikilibros/Políticas y orientaciones}}
*{{L|El uso de Wikilibros/Manual básico del wikipedista}}
*{{L|El uso de Wikilibros/Contribuir a un wikilibro existente}}
*{{L|El uso de Wikilibros/Comenzando un nuevo wikilibro}}
*{{L|El uso de Wikilibros/Donar un libro a Wikilibros}}
*{{L|El uso de Wikilibros/Encontrar un wikilibro}}
*{{L|El uso de Wikilibros/El papel del bibliotecario en Wikilibros}}
*{{L|El uso de Wikilibros/Manual de Wikilibros}}
*{{L|El uso de Wikilibros/Documentación}}
* {{L|:Categoría:El uso de Wikilibros}}
* {{L|Plantilla:El uso de Wikilibros/Página}}
[[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 15:15 10 jun 2026 (UTC)
: {{Hecho}}. Para una próxima ocasión, que requieras solicitar el borrado de una página, puedes colocarle la plantilla {{tl|borrar}} , indicando el motivo de borrado, así aparecerá en las páginas para el borrado. Saludos [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 04:09 11 jun 2026 (UTC)
== Petición de fusión de manuales ==
Buenas, quería hacer una petición para fusionar [[Wikilibros:Manual]] en [[Manual de Wikilibros]].
Como ya mencioné hace dos días en esta misma página y en [[Wikilibros discusión:Manual]], «''Manual de Wikilibros''» es una versión expandida y mejorada de «''Wikilibros:Manual''» pensada para sustituirlo. Ya he completado este manual, y he actualizado los enlaces a lo largo de Wikilibros para que dirijan al nuevo manual. Ahora solo hace falta fusionar el viejo manual en el nuevo, por limpieza, ya que mantener dos manuales con el mismo propósito es una duplicidad que complica el mantenimiento a futuro innecesariamente. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 14:21 12 jun 2026 (UTC)
: {{No|No de momento}}. Para hacer una fusión de historiales, tanto el archivo inicial [[Wikilibros:Manual]] como el final [[Manual de Wikilibros]] debe tener el mismo contenido. Revisando el primero, hay ciertos enlaces que, al hacer la fusión de historiales se perdería. Sugiero tomarse las ediciones con calma. Si bien se agradece los pequeños cambios que has estado realizando, solo recuerda que Wikilibros no es Wikipedia, por lo que no es necesario traer plantillas de allá, que acá solamente ocuparían espacio y quedarán abandonadas. También aplica a las modificaciones en algunas políticas. Primero buscar un [[Wikilibros:Votaciones|consenso]] y luego hacerlas.
:: Respecto a la petición inicial "fusión de historiales", has creado erróneamente el tipo de página del "Manual", ya que correspondería a una página de proyecto y no una entrada principal, como libro. Ante esto, sugiero la dejes tal cual y cuando proceda en hacer la fusión de historiales, encargarme de hacer bien el traslado, así que por favor, no lo hagas por tu propia cuenta.
: [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 22:18 14 jun 2026 (UTC)
::Buenas Mazbel, gracias por revisar mis ediciones, como bien mencionas llegué a Wikilibros tras muchos años en Wikipedia y aún estoy acostumbrándome a las diferencias entre ambos proyectos, te agradezco que me lo señales.
::Sobre las ediciones en las políticas, mi intención no fue cambiar el contenido o el significado de la política, si no mejorar la redacción, ya que por ejemplo la página de [[Wikilibros:Políticas y orientaciones]] comienza listando acuerdos sin dar contexto sobre qué es esa página o qué son las ''políticas y orientaciones'' como tal. No pretendía cambiar las políticas en si porque soy consciente de que se deciden mediante consenso, si no aportar un poco de claridad para los nuevos usuarios que entren a leer esas políticas. Tendré mas cuidado de ahora en adelante con este asunto.
::Sobre el tema de la fusión de historiales, me parece bien el tomarse la fusión con calma.
::Respecto a tu último párrafo, no estoy seguro de haber entendido a qué te refieres cuando comentas que el manual «correspondería a una página de proyecto y no una entrada principal, como libro». ¿Podrías aclararme un poco más este punto?
::Mi razonamiento para ubicarlo como libro está expresado en la sección de motivación, y es que otros libros como «''Manual wiki''» también se encuentran como libros. Por otro lado, este mismo manual también se presenta como un libro normal en las versiones de Wikilibros de otros idiomas, como la inglesa o la francesa.
::Además, mi impresión es que el manual no constituye en sí mismo una política oficial, sino una guía destinada a explicar el funcionamiento de Wikilibros a los usuarios novatos, y por ello debería ser un libro como cualquier otro. En cualquier caso, quedo a la espera de tus comentarios, y gracias de nuevo por revisar mis ediciones y por tus comentarios. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 07:04 15 jun 2026 (UTC)
: Disculpando la tardanza en responder, le comento:
: Sobre «correspondería a una página de proyecto y no una entrada principal, como libro» Si bien el contenido del manual puede tener una estructura similar a la de un libro, su finalidad principal no es educativa en el sentido habitual del proyecto, sino servir como documentación interna sobre el funcionamiento de Wikilibros. Por ello, históricamente ha estado ubicado en el espacio de nombres «Wikilibros:», junto con otras páginas de ayuda, orientación y coordinación comunitaria. (Fíjate que hay páginas denominadas como "Páginas del proyecto" como [[Wikilibros:Manual]] y otras que sólo son catalogadas como "Páginas" ([[Manual de Wikilibros]]) que es lo esperado cuando una crea una nueva entrada de un libro. Esto también se evidencia al momento de hacer traslados de páginas, donde aparece por defecto "Principal" haciendo referencia a una entrada normal o página.
: Agradezco tu disposición para dialogar estos cambios y el trabajo que has dedicado a mejorar la documentación existente. [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 23:50 23 jun 2026 (UTC)
::Entiendo tu razonamiento. Por mi parte, mi preferencia es que el «''Manual de Wikilibros''» sea tratado como un libro normal y se quede con el nombre que tiene ahora debido a los argumentos que ya expuse. Pero entiendo, y me parece razonable, si prefirieses que estuviese bajo el mismo espacio de nombres que otras páginas de orientación. Así que si quieres ponerlo bajo ese nombre, no me opondré. Por mi parte queda zanjado el asunto, expuse mis argumentos pero me parecen razonables los tuyos así que siéntete libre de cambiarlo si así lo consideras.
::<br>Quiero aprovechar la ocasión de que hablamos de estos espacios de nombres, para mencionar otro asunto que me generó bastante confusión cuando llegué a Wikilibros por primera vez. Y es que es algo desconcertante que la propia página de «''Ayuda''» esté bajo el espacio de nombres de «''Wikilibros:''» ([[Wikilibros:Ayuda]]) y no bajo el propio espacio de nombres de «''Ayuda:''» como lo están el resto de páginas de ayuda como por ejemplo [[Ayuda:Preguntas frecuentes]]. En la Wikipedia en español, por ejemplo, la página «principal» de la sección de ayuda se llama «''Ayuda:Contenidos''» ([[w:Ayuda:Contenidos]]) bajo el espacio de nombres «''Ayuda:''» lo cual me parece que es más coherente y más sencillo de entender. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 00:19 24 jun 2026 (UTC)
== Aviso de spam ==
Buenas. Vengo a avisar de dos cuentas de usuario con spam que acaban de ser recientemente creadas, una de ellas ha sido bloqueada por el Filtro antiabusos. Además he observado contenido malsonante en su página de discusión, y probablemente sería mejor directamente borrarlas.
* [[Usuario discusión:No SebastianTheGDAndBoomlingsFan2K16]]
* [[Usuario discusión:No Piero Alonso The Talking Tom Fan 2010]]
Saludos. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 08:19 10 sep 2026 (UTC)
: Páginas eliminadas, usuarios bloqueados tanto local como global. Gracias por el aviso [[Usuario:Mazbel|<span style="font-weight:bold; font-family:cursive, serif;">Mazbel</span>]] [[Usuario discusión:Mazbel|<span style="font-size:small; font-family:cursive, serif;">(Discusión)</span>]] 01:41 11 sep 2026 (UTC)
3sru6pqt5m07e7jkfnu7quep22neq5c
436528
436526
2026-10-14T23:57:58Z
Mazbel
57931
/* Aviso de spam */ archive from [[Wikilibros:Tablón de anuncios a los bibliotecarios]] ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
436528
wikitext
text/x-wiki
{{Archivo}}
== Cambios en el manual y petición de eliminar unas páginas ==
Muy buenas, escribo este post para explicar un asunto en el que estoy trabajando ¡pillad una tacita de té que me ha quedado un poco largo!
Hasta ahora ha existido una duplicidad entre dos páginas:
* «''El uso de Wikilibros''»: Un esbozo de la traducción de la versión en inglés «''The use of Wikibooks''» creado en 2015 pero que nunca se llegó a empezar a escribir realmente.
* «''Wikilibros:Manual''»: Un libro que tan solo contiene 7 páginas muy escuetas cuyo contenido no ha cambiado prácticamente nada desde que se creó en el año 2005.
Mi intención es unificar ambos en «''[[Manual de Wikilibros]]''», llevo unos días trabajando en completar este libro. {{archivar}}
=== Motivación ===
El motivo por el que creo que «''Wikilibros:Manual''» no es un nombre adecuado, es que este manual es un libro como cualquier otro, al igual que existe «''[[Manual wiki]]''» que es un libro acerca del entorno Wiki, «''Wikilibros:Manual''» es un libro acerca de Wikilibros, no una política oficial de este, y por lo tanto, no debería estar bajo el prefijo «''Wikilibros:''».
Además llamarlo simplemente «''Wikilibros:Manual''» es confuso, ya que se solapa por ejemplo con «''[[Wikilibros:Manual de estilo]]''» el cual sí es una política oficial, a diferencia de «''Wikilibros:Manual''» que es simplemente un manual de uso.
Personalmente todas estas cosas me generaron mucha confusión cuando llegué por primera vez a Wikilibros. Sumado a la confusión extra causada porque las páginas de Bienvenida y Ayuda eran a su vez tan solo una página en la que se encontraba una o varias páginas de «''Wikilibros:Manual''» transcluídas (lo cual estoy en proceso de cambiar y mejorar)... Me pareció que la experiencia de bienvenida a wikilibros era sumamente confusa, y por ello estoy trabajando en mejorar todo esto.
En resumen, al igual que se hace en las versiones de Wikilibros de otros idiomas (como el inglés), y como hacemos con el libro de «''Manual wiki''», veo mas limpio y claro que este manual esté alojado bajo «''Manual de Wikilibros''». Y que la página de Bienvenida y Ayuda no sean transclusiones del manual, si no que sean su propia página de bienvenida y ayuda como ocurre en Wikilibros en otros idiomas, o incluso en otras Wikipedias, incluída la Wikipedia en español.
=== ¿Qué pretendo hacer a continuación? ===
Mi intención es terminar de escribir «''[[Manual de Wikilibros]]''» (calculo que terminaré este fin de semana), después, haré que la páginas de Bienvenida no sea una transclusión de este manual, si no su propia página. Luego, actualizaré los enlaces que dirigen al viejo «''Wikilibros:Manual''» para que redireccionen al nuevo «''Manual de Wikilibros''». Y finalmente, cuando esté todo completado, solicitaré una fusión de historiales para fusionar «''Wikilibros:Manual''» en «''Manual de Wikilibros''».
: Al realizar la fusión de historiales, se crea una redirección automática, por lo que no será necesario que se actualicen los antiguos enlaces. [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 04:23 11 jun 2026 (UTC)
=== Petición de borrar algunas redirecciones ===
Debido a todo lo mencionado, una de mis acciones ha sido renombrar el libro «''El uso de Wikilibros''» a «''[[Manual de Wikilibros]]''», para darle un nombre mas claro y descriptivo que refleje mejor el propósito que he explicado.
Pero al trasladar este libro, se han creado muchos artículos con redirecciones que creo que deberían borrarse porque:
# No rompe ningún enlace: antes de que yo empezase a contribuir a este libro, este carecía de contenido, y por lo tanto no hay necesidad de que el «''El uso de Wikilibros''» sea una redirección, ya que no hay nada que redirigir. He buscado por buscadores web, y tampoco he encontrado nada que enlace a «''El uso de Wikilibros''».
# Teniendo en cuenta que no rompe ningún enlace, por simple limpieza, creo que lo mejor es simplemente borrar las páginas que listo abajo.
*{{L|El uso de Wikilibros}}
*{{L|El uso de Wikilibros/Acerca de este libro}}
*{{L|El uso de Wikilibros/Qué es Wikilibros}}
* {{L|El uso de Wikilibros/Crear una cuenta de usuario}}
*{{L|El uso de Wikilibros/Discusión y consenso}}
*{{L|El uso de Wikilibros/Políticas y orientaciones}}
*{{L|El uso de Wikilibros/Manual básico del wikipedista}}
*{{L|El uso de Wikilibros/Contribuir a un wikilibro existente}}
*{{L|El uso de Wikilibros/Comenzando un nuevo wikilibro}}
*{{L|El uso de Wikilibros/Donar un libro a Wikilibros}}
*{{L|El uso de Wikilibros/Encontrar un wikilibro}}
*{{L|El uso de Wikilibros/El papel del bibliotecario en Wikilibros}}
*{{L|El uso de Wikilibros/Manual de Wikilibros}}
*{{L|El uso de Wikilibros/Documentación}}
* {{L|:Categoría:El uso de Wikilibros}}
* {{L|Plantilla:El uso de Wikilibros/Página}}
[[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 15:15 10 jun 2026 (UTC)
: {{Hecho}}. Para una próxima ocasión, que requieras solicitar el borrado de una página, puedes colocarle la plantilla {{tl|borrar}} , indicando el motivo de borrado, así aparecerá en las páginas para el borrado. Saludos [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 04:09 11 jun 2026 (UTC)
== Petición de fusión de manuales ==
Buenas, quería hacer una petición para fusionar [[Wikilibros:Manual]] en [[Manual de Wikilibros]].
Como ya mencioné hace dos días en esta misma página y en [[Wikilibros discusión:Manual]], «''Manual de Wikilibros''» es una versión expandida y mejorada de «''Wikilibros:Manual''» pensada para sustituirlo. Ya he completado este manual, y he actualizado los enlaces a lo largo de Wikilibros para que dirijan al nuevo manual. Ahora solo hace falta fusionar el viejo manual en el nuevo, por limpieza, ya que mantener dos manuales con el mismo propósito es una duplicidad que complica el mantenimiento a futuro innecesariamente. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 14:21 12 jun 2026 (UTC)
: {{No|No de momento}}. Para hacer una fusión de historiales, tanto el archivo inicial [[Wikilibros:Manual]] como el final [[Manual de Wikilibros]] debe tener el mismo contenido. Revisando el primero, hay ciertos enlaces que, al hacer la fusión de historiales se perdería. Sugiero tomarse las ediciones con calma. Si bien se agradece los pequeños cambios que has estado realizando, solo recuerda que Wikilibros no es Wikipedia, por lo que no es necesario traer plantillas de allá, que acá solamente ocuparían espacio y quedarán abandonadas. También aplica a las modificaciones en algunas políticas. Primero buscar un [[Wikilibros:Votaciones|consenso]] y luego hacerlas.
:: Respecto a la petición inicial "fusión de historiales", has creado erróneamente el tipo de página del "Manual", ya que correspondería a una página de proyecto y no una entrada principal, como libro. Ante esto, sugiero la dejes tal cual y cuando proceda en hacer la fusión de historiales, encargarme de hacer bien el traslado, así que por favor, no lo hagas por tu propia cuenta.
: [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 22:18 14 jun 2026 (UTC)
::Buenas Mazbel, gracias por revisar mis ediciones, como bien mencionas llegué a Wikilibros tras muchos años en Wikipedia y aún estoy acostumbrándome a las diferencias entre ambos proyectos, te agradezco que me lo señales.
::Sobre las ediciones en las políticas, mi intención no fue cambiar el contenido o el significado de la política, si no mejorar la redacción, ya que por ejemplo la página de [[Wikilibros:Políticas y orientaciones]] comienza listando acuerdos sin dar contexto sobre qué es esa página o qué son las ''políticas y orientaciones'' como tal. No pretendía cambiar las políticas en si porque soy consciente de que se deciden mediante consenso, si no aportar un poco de claridad para los nuevos usuarios que entren a leer esas políticas. Tendré mas cuidado de ahora en adelante con este asunto.
::Sobre el tema de la fusión de historiales, me parece bien el tomarse la fusión con calma.
::Respecto a tu último párrafo, no estoy seguro de haber entendido a qué te refieres cuando comentas que el manual «correspondería a una página de proyecto y no una entrada principal, como libro». ¿Podrías aclararme un poco más este punto?
::Mi razonamiento para ubicarlo como libro está expresado en la sección de motivación, y es que otros libros como «''Manual wiki''» también se encuentran como libros. Por otro lado, este mismo manual también se presenta como un libro normal en las versiones de Wikilibros de otros idiomas, como la inglesa o la francesa.
::Además, mi impresión es que el manual no constituye en sí mismo una política oficial, sino una guía destinada a explicar el funcionamiento de Wikilibros a los usuarios novatos, y por ello debería ser un libro como cualquier otro. En cualquier caso, quedo a la espera de tus comentarios, y gracias de nuevo por revisar mis ediciones y por tus comentarios. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 07:04 15 jun 2026 (UTC)
: Disculpando la tardanza en responder, le comento:
: Sobre «correspondería a una página de proyecto y no una entrada principal, como libro» Si bien el contenido del manual puede tener una estructura similar a la de un libro, su finalidad principal no es educativa en el sentido habitual del proyecto, sino servir como documentación interna sobre el funcionamiento de Wikilibros. Por ello, históricamente ha estado ubicado en el espacio de nombres «Wikilibros:», junto con otras páginas de ayuda, orientación y coordinación comunitaria. (Fíjate que hay páginas denominadas como "Páginas del proyecto" como [[Wikilibros:Manual]] y otras que sólo son catalogadas como "Páginas" ([[Manual de Wikilibros]]) que es lo esperado cuando una crea una nueva entrada de un libro. Esto también se evidencia al momento de hacer traslados de páginas, donde aparece por defecto "Principal" haciendo referencia a una entrada normal o página.
: Agradezco tu disposición para dialogar estos cambios y el trabajo que has dedicado a mejorar la documentación existente. [[User:Mazbel|<span style="color:#000000;font-weight:bold;font-family:cursive, serif">Mazbel</span>]] [[User talk:Mazbel|<span style="color:#000000;font-size:small;font-family:cursive, serif;">(Talk)</span>]] 23:50 23 jun 2026 (UTC)
::Entiendo tu razonamiento. Por mi parte, mi preferencia es que el «''Manual de Wikilibros''» sea tratado como un libro normal y se quede con el nombre que tiene ahora debido a los argumentos que ya expuse. Pero entiendo, y me parece razonable, si prefirieses que estuviese bajo el mismo espacio de nombres que otras páginas de orientación. Así que si quieres ponerlo bajo ese nombre, no me opondré. Por mi parte queda zanjado el asunto, expuse mis argumentos pero me parecen razonables los tuyos así que siéntete libre de cambiarlo si así lo consideras.
::<br>Quiero aprovechar la ocasión de que hablamos de estos espacios de nombres, para mencionar otro asunto que me generó bastante confusión cuando llegué a Wikilibros por primera vez. Y es que es algo desconcertante que la propia página de «''Ayuda''» esté bajo el espacio de nombres de «''Wikilibros:''» ([[Wikilibros:Ayuda]]) y no bajo el propio espacio de nombres de «''Ayuda:''» como lo están el resto de páginas de ayuda como por ejemplo [[Ayuda:Preguntas frecuentes]]. En la Wikipedia en español, por ejemplo, la página «principal» de la sección de ayuda se llama «''Ayuda:Contenidos''» ([[w:Ayuda:Contenidos]]) bajo el espacio de nombres «''Ayuda:''» lo cual me parece que es más coherente y más sencillo de entender. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 00:19 24 jun 2026 (UTC)
== Aviso de spam ==
Buenas. Vengo a avisar de dos cuentas de usuario con spam que acaban de ser recientemente creadas, una de ellas ha sido bloqueada por el Filtro antiabusos. Además he observado contenido malsonante en su página de discusión, y probablemente sería mejor directamente borrarlas.
* [[Usuario discusión:No SebastianTheGDAndBoomlingsFan2K16]]
* [[Usuario discusión:No Piero Alonso The Talking Tom Fan 2010]]
Saludos. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 08:19 10 sep 2026 (UTC)
: Páginas eliminadas, usuarios bloqueados tanto local como global. Gracias por el aviso [[Usuario:Mazbel|<span style="font-weight:bold; font-family:cursive, serif;">Mazbel</span>]] [[Usuario discusión:Mazbel|<span style="font-size:small; font-family:cursive, serif;">(Discusión)</span>]] 01:41 11 sep 2026 (UTC)
== Aviso de spam ==
Buenas. Vengo a avisar de esta cuenta que recientemente ha estado realizando vandalismos: [[Especial:Contribuciones/~2026-49864-76]]. Saludos. [[Usuario:Antimundo|Antimundo]] ([[Usuario discusión:Antimundo|discusión]]) 13:49 15 sep 2026 (UTC)
: Gracias por el aviso. Usuario bloqueado. [[Usuario:Mazbel|<span style="font-weight:bold; font-family:cursive, serif;">Mazbel</span>]] [[Usuario discusión:Mazbel|<span style="font-size:small; font-family:cursive, serif;">(Discusión)</span>]] 14:37 15 sep 2026 (UTC)
brpb4ugb5nb1ct6snx91z2wxurvcmtz
Wikichicos/Geografía de España/Mi país y el mundo/Organización territorial de España/Comunidades autónomas/Andalucía
0
64772
436524
435299
2026-10-14T16:16:47Z
AAbelardoo
123302
imagen en español
436524
wikitext
text/x-wiki
[[Archivo:Localización de Andalucía.svg|miniaturadeimagen|Localización de Andalucía en el Sur de España]]
[[Archivo:Andalusien Karte-es.png|miniaturadeimagen|Principales ciudades de Andalucía]]
'''Andalucía''' es una comunidad autónoma española y está reconocida como nacionalidad histórica. Se encuentra en el sur de la península ibérica y está formada por ocho provincias: '''Almería, Cádiz, Córdoba, Granada, Huelva, Jaén, Málaga y Sevilla'''. '''Su capital es Sevilla'''.
Es la comunidad autónoma más poblada de España y la segunda más extensa, con unos '''87.600 km²'''. Limita con '''Portugal, Extremadura, Castilla-La Mancha, Murcia, el océano Atlántico y el mar Mediterráneo'''.
Se constituyó como comunidad autónoma en '''1981''', después de las manifestaciones de 1977 y del referéndum de 1980, en el que los andaluces apoyaron la autonomía.
=== Geografía ===
[[Archivo:Relieve andalucia.png|miniaturadeimagen|Relieve de Andalucía]]
* '''Situación:''' Andalucía está en el sur de la península ibérica, entre el '''océano Atlántico y el mar Mediterráneo'''. Tiene '''87.268 km²''' y está formada por '''8 provincias'''. Su capital es '''Sevilla'''.
* '''Relieve:''' se divide en '''Sierra Morena, depresión del Guadalquivir y cordilleras Béticas'''. En Sierra Nevada se encuentra el '''Mulhacén (3.478 m)''', la mayor altura de la península ibérica.
* '''Clima:''' principalmente '''mediterráneo''', con veranos calurosos y secos e inviernos suaves. Hay grandes diferencias entre zonas lluviosas, como '''Grazalema''', y zonas muy secas, como '''Tabernas'''.
* '''Ríos:''' pertenecen a las vertientes '''atlántica y mediterránea'''. El '''Guadalquivir''', de 657 km, es el río más largo de Andalucía.
* '''Flora y fauna:''' predominan los bosques mediterráneos, con encinas, alcornoques, pinos y pinsapos. Destacan especies como el '''lince ibérico, ciervo, cabra montés, águila y flamenco'''.
* '''Espacios protegidos:''' cerca del '''20 % del territorio''' está protegido. Destacan '''Doñana, Sierra Nevada, Cazorla, Segura y Las Villas, Tabernas y Cabo de Gata'''.
=== Historia ===
* '''Historia:''' Andalucía recibió la influencia de pueblos como '''fenicios, romanos, musulmanes y castellanos'''. Córdoba fue un importante centro de Al-Ándalus y el reino nazarí de Granada permaneció hasta '''1492'''.
* '''Autonomía:''' Andalucía se constituyó como comunidad autónoma en '''1981''', después del proceso iniciado con las movilizaciones de 1977 y el referéndum de 1980.
=== Población ===
* '''Población:''' es la '''comunidad autónoma más poblada de España'''. La población se concentra sobre todo en el '''valle del Guadalquivir, las costas y las áreas metropolitanas'''. Sevilla y Málaga son los municipios más poblados.
=== Economía ===
* '''Economía:''' predominan los '''servicios''', especialmente el turismo, y la '''agricultura'''. La industria tiene un peso menor y el desempleo ha sido históricamente elevado.
=== Cultura y tradiciones de Andalucía ===
* '''Arte:''' destacan '''Velázquez, Murillo, Picasso y Zurbarán'''. Sobresalen monumentos como la '''Alhambra, la Mezquita de Córdoba, la Giralda e Itálica'''.
* '''Literatura:''' destacan '''Góngora, Bécquer, Juan Ramón Jiménez, los hermanos Machado y García Lorca'''.
* '''Música:''' el '''flamenco''' es una de las principales expresiones culturales andaluzas. Destacan '''Manuel de Falla, Camarón y Paco de Lucía'''.
* '''Gastronomía:''' basada en la '''dieta mediterránea'''. Son típicos el '''gazpacho, salmorejo, migas, pescaíto frito, mariscos y jamón'''.
* '''Repostería y vinos:''' destacan '''mantecados, polvorones, pestiños, alfajores''' y los vinos de '''Jerez, Huelva y Málaga'''.
* '''Costumbres:''' destacan el '''traje de flamenca''', los sombreros tradicionales y el '''arte ecuestre del caballo andaluz'''.
p3nq1fp6homcpq7b3tfzw2os34n19ax
436525
436524
2026-10-14T16:17:12Z
AAbelardoo
123302
Añadiendo la [[Categoría:Wikichicos/Geografía de España]] mediante [[Wikipedia:HotCat|HotCat]]
436525
wikitext
text/x-wiki
[[Archivo:Localización de Andalucía.svg|miniaturadeimagen|Localización de Andalucía en el Sur de España]]
[[Archivo:Andalusien Karte-es.png|miniaturadeimagen|Principales ciudades de Andalucía]]
'''Andalucía''' es una comunidad autónoma española y está reconocida como nacionalidad histórica. Se encuentra en el sur de la península ibérica y está formada por ocho provincias: '''Almería, Cádiz, Córdoba, Granada, Huelva, Jaén, Málaga y Sevilla'''. '''Su capital es Sevilla'''.
Es la comunidad autónoma más poblada de España y la segunda más extensa, con unos '''87.600 km²'''. Limita con '''Portugal, Extremadura, Castilla-La Mancha, Murcia, el océano Atlántico y el mar Mediterráneo'''.
Se constituyó como comunidad autónoma en '''1981''', después de las manifestaciones de 1977 y del referéndum de 1980, en el que los andaluces apoyaron la autonomía.
=== Geografía ===
[[Archivo:Relieve andalucia.png|miniaturadeimagen|Relieve de Andalucía]]
* '''Situación:''' Andalucía está en el sur de la península ibérica, entre el '''océano Atlántico y el mar Mediterráneo'''. Tiene '''87.268 km²''' y está formada por '''8 provincias'''. Su capital es '''Sevilla'''.
* '''Relieve:''' se divide en '''Sierra Morena, depresión del Guadalquivir y cordilleras Béticas'''. En Sierra Nevada se encuentra el '''Mulhacén (3.478 m)''', la mayor altura de la península ibérica.
* '''Clima:''' principalmente '''mediterráneo''', con veranos calurosos y secos e inviernos suaves. Hay grandes diferencias entre zonas lluviosas, como '''Grazalema''', y zonas muy secas, como '''Tabernas'''.
* '''Ríos:''' pertenecen a las vertientes '''atlántica y mediterránea'''. El '''Guadalquivir''', de 657 km, es el río más largo de Andalucía.
* '''Flora y fauna:''' predominan los bosques mediterráneos, con encinas, alcornoques, pinos y pinsapos. Destacan especies como el '''lince ibérico, ciervo, cabra montés, águila y flamenco'''.
* '''Espacios protegidos:''' cerca del '''20 % del territorio''' está protegido. Destacan '''Doñana, Sierra Nevada, Cazorla, Segura y Las Villas, Tabernas y Cabo de Gata'''.
=== Historia ===
* '''Historia:''' Andalucía recibió la influencia de pueblos como '''fenicios, romanos, musulmanes y castellanos'''. Córdoba fue un importante centro de Al-Ándalus y el reino nazarí de Granada permaneció hasta '''1492'''.
* '''Autonomía:''' Andalucía se constituyó como comunidad autónoma en '''1981''', después del proceso iniciado con las movilizaciones de 1977 y el referéndum de 1980.
=== Población ===
* '''Población:''' es la '''comunidad autónoma más poblada de España'''. La población se concentra sobre todo en el '''valle del Guadalquivir, las costas y las áreas metropolitanas'''. Sevilla y Málaga son los municipios más poblados.
=== Economía ===
* '''Economía:''' predominan los '''servicios''', especialmente el turismo, y la '''agricultura'''. La industria tiene un peso menor y el desempleo ha sido históricamente elevado.
=== Cultura y tradiciones de Andalucía ===
* '''Arte:''' destacan '''Velázquez, Murillo, Picasso y Zurbarán'''. Sobresalen monumentos como la '''Alhambra, la Mezquita de Córdoba, la Giralda e Itálica'''.
* '''Literatura:''' destacan '''Góngora, Bécquer, Juan Ramón Jiménez, los hermanos Machado y García Lorca'''.
* '''Música:''' el '''flamenco''' es una de las principales expresiones culturales andaluzas. Destacan '''Manuel de Falla, Camarón y Paco de Lucía'''.
* '''Gastronomía:''' basada en la '''dieta mediterránea'''. Son típicos el '''gazpacho, salmorejo, migas, pescaíto frito, mariscos y jamón'''.
* '''Repostería y vinos:''' destacan '''mantecados, polvorones, pestiños, alfajores''' y los vinos de '''Jerez, Huelva y Málaga'''.
* '''Costumbres:''' destacan el '''traje de flamenca''', los sombreros tradicionales y el '''arte ecuestre del caballo andaluz'''.
[[Categoría:Wikichicos/Geografía de España]]
qtribydlpjq9rr3m4zbupyefurpprwa
Haskell/Variables y funciones
0
64935
436488
436486
2026-10-14T12:10:25Z
Luciérnaga de conocimiento
119502
436488
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Variables y funciones}}
''Todos los ejemplos de este capítulo pueden guardarse en un archivo y ejecutarse usando GHC. No incluyas `Prelude>` en ninguno de los ejemplos. Cuando aparezca este comando, significa que el código siguiente se ejecutó en GHCi. Cuando no aparezca el comando, basta con copiar el código completo.''
== Variables ==
En el capítulo anterior, usamos GHCi como una calculadora, algo que resulta práctico únicamente para cálculos breves. Para realizar cálculos más complejos y escribir un programa en Haskell, generalmente tenemos que seguir y comprobar los resultados intermedios.
Podemos hacerlo asignando nombres. A estos nombres los llamamos ''variables''. Cuando se ejecuta un programa, cada variable se sustituye por un ''valor'' al que hace referencia. Por ejemplo, considera lo siguiente:
{{Haskell/GHCi|1=
Prelude> 3.141592653 * 5^2
78.539816325
}}
Este fue el cálculo aproximado del área de un círculo de radio <code>5</code>, de acuerdo con la fórmula <math>A = \pi r^2</math>. Por supuesto, resulta bastante laborioso escribir todos los dígitos de <math>\pi \approx 3,141592653</math>, o incluso recordar los primeros cinco. Por eso, para evitar repeticiones, podemos hacer que la máquina recuerde estos valores una sola vez, de modo que podamos utilizarlos siempre que sea necesario. Esta abstracción nos permite concentrarnos en otras partes más importantes. En este ejemplo, Haskell ya dispone de una variable llamada <code>pi</code> que almacena más de 15 dígitos de <math>\pi</math>, lo que hace que el código sea más claro y, además, nos permite obtener resultados más precisos.
{{Haskell/GHCi|1=
Prelude> pi
3.141592653589793
Prelude> pi * 5^2
78.53981633974483
}}
Observa cómo la variable <code>pi</code> y su valor, <code>3.141592653589793</code>, se sustituyen mutuamente en los cálculos.
== Archivos de código en Haskell ==
Además de realizar cálculos ocasionalmente en GHCi, puedes guardar tu código en un archivo Haskell, que es un archivo de texto con la extensión <tt>.hs</tt>. Se recomienda utilizar un editor de texto diseñado para la programación (consulta el [[w:Editor de texto|artículo de Wikipedia sobre editores de texto]]). La gran mayoría de ellos permiten ''resaltar la sintaxis'', es decir, colorear el código fuente para facilitar su lectura. Vim y Emacs son dos opciones bastante populares entre los programadores.
Para mantener todo organizado, crea también un directorio nuevo (una carpeta) en tu computadora para guardar los archivos Haskell que vayas creando al resolver los ejercicios de este libro. Vamos, crea un directorio llamado <tt>HaskellWikibook</tt>, por ejemplo, y dentro de él un archivo llamado <tt>Varfun.hs</tt> que contenga el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5.0
</syntaxhighlight>
Este programa define la variable <code>r</code> con el valor <code>5.0</code>.
Nota: asegúrate de que no haya espacios en blanco al comienzo de las líneas, porque Haskell distingue los espacios de indentación.
Después, abre una terminal en el directorio <tt>HaskellWikibook</tt> que creaste, ejecuta GHCi y carga el archivo <tt>Varfun.hs</tt> usando el comando <code>:load</code>:
{{Haskell/GHCi|1=
Prelude> :load Varfun.hs
[1 of 1] Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
}}
Conviene saber que <code>:load</code> puede abreviarse como <code>:l</code>: <code>:l Varfun.hs</code>.
Si GHCi devuelve un error como <code>Could not find module 'Varfun.hs'</code>, significa que probablemente te encuentras en el directorio equivocado. Prueba el comando <code>:cd</code> para cambiar el directorio actual desde GHCi (por ejemplo, <code>:cd HaskellWikibook</code>).
Después de cargar el archivo en la sesión de GHCi, verás que la línea de comandos cambia de "Prelude" a "*Main". Ahora puedes utilizar la variable <code>r</code> que definiste en el archivo.
{{Haskell/GHCi|1=
*Main> r
5.0
*Main> pi * r^2
78.53981633974483
}}
Acabamos de calcular el área de un círculo de radio 5,0 utilizando la fórmula <math>\pi r^2</math>. Lo que hicimos fue utilizar <code>r</code>, que definimos en el archivo <tt>Varfun.hs</tt>, y <code>pi</code>, que ya está definida en otro lugar.
Ahora vamos a facilitar el acceso a este valor definiendo también un nombre para él. Abre nuevamente el archivo y cambia su contenido por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 5.0
area = pi * r ^ 2
</syntaxhighlight>
Guárdalo y vuelve a cargarlo en GHCi mediante <code>:reload</code>, o simplemente <code>:r</code>:
{{Haskell/GHCi|1=
*Main> :reload
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
}}
Ahora tenemos dos variables: <code>r</code> y <code>area</code>.
{{Haskell/GHCi|1=
*Main> area
78.53981633974483
*Main> area / r
15.707963267948966
}}
{{nota|La palabra <code>let</code> es la que deberíamos utilizar para definir nuevas variables directamente en GHCi, sin necesidad de editar un archivo de código. Aunque hacerlo de esta manera puede resultar práctico, no siempre es lo más conveniente para tareas complejas. En esos casos, es preferible utilizar archivos.}}
== Comentarios ==
Además del propio código, los archivos de código fuente pueden contener textos conocidos como ''comentarios'', que el compilador ignora. En Haskell existen dos tipos de comentarios. El primero comienza con <code>--</code> y se extiende hasta el final de la línea:
<syntaxhighlight lang = "haskell">
x = 5 -- x es 5.
y = 6 -- y es 6.
-- z = 7 -- z no está definida.
</syntaxhighlight>
En este caso, <code>x</code> e <code>y</code> están efectivamente definidas en el código, pero <code>z</code> no lo está.
El segundo tipo de comentario está delimitado por <code>{- ... -}</code> y puede abarcar varias líneas:
<syntaxhighlight lang = "haskell">
answer = 2 * {-
bloque de comentario de varias líneas y...
-} 3 {- comentario en medio de la línea -} * 7
</syntaxhighlight>
Los comentarios se utilizan para explicar partes de un programa o realizar anotaciones sobre cualquier aspecto del contexto. Es importante señalar que abusar de los comentarios puede, en realidad, dificultar la lectura del propio código. Además, los comentarios desactualizados también pueden generar confusiones.
== Variables en lenguajes imperativos ==
Los lectores familiarizados con los lenguajes de programación imperativos notarán que las variables en Haskell se comportan de manera muy diferente a las variables en C, por ejemplo.
Si no tienes experiencia previa en programación, puedes saltarte esta sección, aunque puede ayudarte a comprender las situaciones en las que se compara el comportamiento de Haskell con el de otros lenguajes. Muchos libros sobre Haskell lo hacen, por ejemplo.
La ''programación imperativa'' trata las variables como posiciones en la memoria de la computadora. Este enfoque está relacionado con el funcionamiento básico de una computadora. Los programas imperativos indican explícitamente a la computadora lo que debe hacer. Los lenguajes de alto nivel, aunque pueden estar bastante alejados de estos conceptos, todavía conservan parte de ellos en el sentido de que siguen utilizando este patrón de programación «paso a paso». En contraste, la ''programación funcional'' ofrece una manera diferente de pensar, utilizando términos matemáticos y dejando de lado las instrucciones directas a la computadora, que solo son traducidas por el compilador a algo que la máquina pueda interpretar y procesar.
Veamos un ejemplo. El siguiente código no funcionaría en Haskell:
<syntaxhighlight lang = "haskell">
r = 5
r = 2
</syntaxhighlight>
Un programador de lenguajes imperativos interpretaría esto como: primero, definir <code>r = 5</code> y después redefinirla como <code>r = 2</code>. En Haskell, sin embargo, el compilador respondería con un error: «múltiples declaraciones de <code>r</code>». Dentro de un ámbito determinado, una variable de Haskell se define una sola vez y su definición no puede cambiar.
Las variables de Haskell parecen ''invariables'', pero en realidad se comportan como variables matemáticas. En Matemáticas nunca vemos que una variable cambie de valor dentro de un mismo problema, y lo mismo sucede en Haskell.
Más precisamente, las variables de Haskell son ''inmutables'': sus valores solo varían de acuerdo con los datos que introducimos en el programa. No podemos definir <code>r</code> de dos maneras diferentes en un mismo código, pero podemos cambiar su valor modificando el archivo. Cambiemos el código anterior por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 2.0
area = pi * r ^ 2
</syntaxhighlight>
Por supuesto, funcionará. Hemos cambiado <code>r</code> en el único lugar donde está definida, y eso modifica su valor en el resto del programa.
En problemas reales, los programas en Haskell dejan ''algunos'' valores sin definir en el código. Esos valores se definen más adelante, cuando el programa obtiene datos de un archivo o de una acción externa. Por ahora, sin embargo, nos limitaremos a definir variables internamente. Aprenderemos sobre las interacciones con el mundo exterior en capítulos posteriores.
Veamos otro ejemplo de la gran diferencia entre Haskell y los lenguajes imperativos:
<syntaxhighlight lang = "haskell">
r = r + 1
</syntaxhighlight>
En lugar de «incrementar el valor de <code>r</code>», es decir, actualizar el valor almacenado en la memoria, este código en Haskell constituye una definición recursiva de <code>r</code>, o sea, la define en términos de sí misma. No te preocupes, pues explicaremos la [[Haskell/Recursión|recursión]] más adelante. En este caso concreto, si <code>r</code> ya hubiera sido definida con algún valor, el compilador devolvería un mensaje de error, como explicamos anteriormente. Si <code>r</code> se hubiera definido con el valor 5, escribir <code>r = r + 1</code> sería equivalente a intentar afirmar que <math>5 = 5 + 1</math> en Matemáticas, lo cual es evidentemente incorrecto.
Como los valores no cambian dentro de un mismo programa, las variables pueden definirse en el orden que queramos. Por ejemplo, los dos códigos siguientes son exactamente equivalentes:
{|border="0"
|-
||<syntaxhighlight lang = "haskell">
y = x * 2
x = 3
</syntaxhighlight>
||<syntaxhighlight lang = "haskell">
x = 3
y = x * 2
</syntaxhighlight>
|}
En Haskell no existe la noción de que «<code>x</code> se declaró antes que <code>y</code>», o viceversa. Por supuesto, para utilizar <code>y</code> seguimos necesitando el valor de <code>x</code>, pero el orden no nos importa, ni tampoco al compilador.
== Funciones ==
Modificar el programa cada vez que queramos calcular el área de un círculo diferente resulta tedioso y nos limita a un círculo por vez. Podríamos calcular dos áreas duplicando todos los cálculos en nuestro código y definiendo <code>r2</code> y <code>area2</code><ref group=nota>Podemos observar aquí que los nombres de las variables pueden contener números y letras. Sin embargo, toda variable ''debe'' comenzar con una letra minúscula, seguida de otras letras (también mayúsculas), números, guiones bajos (_) o apóstrofos (').</ref>
<syntaxhighlight lang = "haskell">
r = 5
area = pi * r ^ 2
r2 = 3
area2 = pi * r2 ^ 2
</syntaxhighlight>
Para evitar esta repetición constante, es preferible añadir simplemente una ''función'' para calcular el área y aplicarla a diferentes radios.
Una ''función'' recibe un ''argumento'' (o ''parámetro'') y devuelve un resultado, exactamente igual que en Matemáticas. En Haskell, las funciones se definen de la misma manera que las variables, salvo que debemos indicar sus argumentos en el lado izquierdo de la expresión. Por ejemplo, el siguiente código define <code>area</code>, cuyo argumento es <code>r</code>:
<syntaxhighlight lang = "haskell">
area r = pi * r ^ 2
</syntaxhighlight>
Observa la sintaxis: primero aparece el nombre de la función (<code>area</code>), seguido de un espacio en blanco y de su argumento (<code>r</code>). Después aparece el signo <code>=</code> y la definición de la función, que utiliza el argumento de entrada en su cálculo.
Ahora podemos probar diferentes valores del radio y ''llamar'' a la función con ellos. Guarda el código anterior en un archivo, ábrelo en GHCi y prueba lo siguiente:
{{Haskell/GHCi|1=
*Main> area 5
78.53981633974483
*Main> area 3
28.274333882308138
*Main> area 17
907.9202768874502
}}
Acabamos de ''llamar'' a la función con diferentes valores y hemos calculado las áreas de tres círculos distintos.
Matemáticamente, el cálculo del área puede representarse mediante <math>A(r) = \pi \cdot r ^ 2</math>. Para calcular las áreas, escribiríamos <math>A(5) = 78.54</math> o <math>A(3) = 28.27</math>. Haskell también permite utilizar paréntesis, pero por convención suelen omitirse para que el código tenga menos símbolos y sea más legible.
Aun así, los paréntesis se utilizan para agrupar ''expresiones'' (cualquier código que devuelva un valor) que deben calcularse en conjunto. Observa cómo se interpretan de manera diferente las siguientes expresiones:
<syntaxhighlight lang = "haskell">
5 * 3 + 2 -- 15 + 2 = 17 (la multiplicación se realiza antes que la suma)
5 * (3 + 2) -- 5 * 5 = 25 (los paréntesis obligan a calcular primero la suma)
area 5 * 3 -- (area 5) * 3
area (5 * 3) -- area 15
</syntaxhighlight>
Del mismo modo que la multiplicación se realiza antes que la suma, observa que las aplicaciones de funciones en Haskell tienen una precedencia mayor que cualquier operador, ya sea <code>+</code> o <code>*</code>, por ejemplo.
== Evaluación de expresiones ==
¿Qué sucede exactamente cuando introducimos una expresión en GHCi? Después de pulsar «Enter», se evalúa. Esto significa que cada función se sustituye por su definición y se realizan los cálculos hasta que queda un único valor final. Por ejemplo, al ejecutar <code>area 5</code>, sucede lo siguiente:
<syntaxhighlight lang=haskell>
area 5 -- todas las apariciones de 'r' a la derecha se sustituyen por '5'
pi * 5 ^ 2 -- 'pi' se sustituye por un valor aproximado
3.141592653589793 * 5 ^ 2 -- se realiza la operación de potenciación '5 ^ 2'
3.141592653589793 * 25 -- se realiza la operación de multiplicación
78.53981633974483 -- resultado final
</syntaxhighlight>
Cuando utilizamos GHCi, el resultado de ''aplicar'' o ''llamar'' a la función, siguiendo el procedimiento anterior, aparece en la pantalla.
Veamos ahora algunas funciones más:
<syntaxhighlight lang = "haskell">
duplicar x = 2 * x
cuadruplicar x = double (double x)
cuadrado x = x * x
mitad x = x / 2
</syntaxhighlight>
{{Haskell/Ejercicios|1=
* Explica cómo evaluaría GHCi <code>cuadruplicar 5</code>.
* Define una función que reste 12 a la mitad de su argumento.
}}
== Parámetros múltiples ==
Las funciones también pueden tener más de un argumento. Por ejemplo, para calcular el área de un rectángulo necesitamos su longitud y su anchura:
<syntaxhighlight lang = "haskell">
areaRectang a b = a * b
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaRectang 5 10
50
}}
Otro ejemplo es el área de un triángulo, <math>A = \frac{bh}{2}</math>:
<syntaxhighlight lang="haskell">
areaTriang b h = (b * h) / 2
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaTriang 3 9
13.5
}}
Como puedes ver, los argumentos se separan mediante espacios. Por eso, a veces es necesario utilizar paréntesis para agrupar expresiones. Por ejemplo, no podemos escribir el cuádruple de un valor de la siguiente manera:
<syntaxhighlight lang = "haskell">
cuadruple x = double double x -- error
</syntaxhighlight>
Esto aplicaría la función <code>double</code> a dos argumentos: <code>double</code> y <code>x</code>. Sí es posible que las ''funciones sean argumentos de otras funciones'', como veremos más adelante, pero eso no es lo que queremos hacer aquí. Para que esta función funcione, necesitamos utilizar paréntesis:
<syntaxhighlight lang = "haskell">
cuadruple x = double (double x)
</syntaxhighlight>
Los argumentos siempre se pasan en el orden en que aparecen. Por ejemplo:
<syntaxhighlight lang = "haskell">
menos x y = x - y
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> menos 10 5
5
*Main> menos 5 10
-5
}}
Aquí, <code>menos 10 5</code> evalúa la expresión <code>10 - 5</code>, mientras que <code>menos 5 10</code> evalúa <code>5 - 10</code>, debido al cambio en el orden de los argumentos.
{{Haskell/Ejercicios|1=
* Escribe una función para calcular el volumen de una caja.
* ¿Aproximadamente cuántas piedras se utilizaron para construir las famosas pirámides de Guiza? Pista: tendrás que estimar el volumen de la pirámide y el volumen de cada bloque de piedra.
}}
== Combinación de funciones ==
Por supuesto, puedes utilizar otras funciones para definir las tuyas, del mismo modo que ya lo has hecho utilizando la suma, <code>+</code>, o la multiplicación, <code>*</code>. De hecho, los operadores también se definen como funciones en Haskell. Por ejemplo, para calcular el área de un cuadrado, podemos reutilizar la función que calcula el área de un rectángulo:
<syntaxhighlight lang = "haskell">
areaRetang a b = a * b
areaCuad l = areaRetang l l
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaCuad 5
25
}}
Al fin y al cabo, un cuadrado es un rectángulo cuyos lados son iguales.
{{Haskell/Ejercicios|1=
* Escribe una función que calcule el volumen de un cilindro. El volumen de un cilindro es el área de su base, que es un círculo, multiplicada por la altura. Como ya has programado la función que calcula el área de un círculo en este capítulo, puedes reutilizarla aquí.
}}
== Definición de funciones locales ==
=== Uso de <code>where</code> ===
Cuando definimos una función, a veces necesitamos calcular valores intermedios que son ''locales'' y se utilizan únicamente dentro de esa función. Considera la [[w:teorema de Herón|fórmula de Herón]]: <math>A = \sqrt{p(p-a)(p-b)(p-c)}</math>, donde <math>p</math> es la mitad del perímetro del triángulo. Este es el cálculo del área de un triángulo cuyos lados miden <code>a</code>, <code>b</code> y <code>c</code>:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
where
s = (a + b + c) / 2
</syntaxhighlight>
La variable <code>s</code> representa la mitad del perímetro. Sería tedioso y propenso a errores tener que escribir <code>(a + b + c)/2</code> cada vez que necesitáramos este valor dentro de <code>herao</code>. <code>sqrt</code> calcula la raíz cuadrada de su argumento (recuerda que significa ''square root'' en inglés).
Escribir las definiciones por separado no funcionaría. Observa:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2 -- a, b y c no están definidas aquí
</syntaxhighlight>
El compilador señalaría que <code>a</code>, <code>b</code> y <code>c</code> solo están disponibles en el lado derecho de <code>herao</code>, mientras que la definición de <code>s</code> no forma parte del lado derecho de <code>herao</code>. Para incluirla allí, utilizamos la palabra clave <code>where</code>.
Observa que tanto <code>where</code> como la definición de <code>s</code> están indentadas con cuatro espacios en blanco. Esto es importante para delimitar qué pertenece a cada bloque. Veamos otros ejemplos del uso de <code>where</code>:
<syntaxhighlight lang = "haskell">
areaTriangTrig a b c = c * altura / 2 -- usando trigonometría
where
cosAlfa = (b ^ 2 + c ^ 2 - a ^ 2) / (2 * b * c)
sinAlfa = sqrt (1 - cosAlfa ^ 2)
altura = b * sinAlfa
areaTriangHeron a b c = resultado -- usa la fórmula de Herón
where
resultado = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2
</syntaxhighlight>
== Ámbito ==
Observa atentamente el ejemplo anterior: fíjate en que utilizamos las variables <code>a</code>, <code>b</code> y <code>c</code> dos veces, en cada una de las funciones definidas. ¿Cómo es posible?
Considera el siguiente procedimiento en GHCi:
{{Haskell/GHCi|1=
Prelude> let r = 0
Prelude> let area r = pi * r ^ 2
Prelude> area 5
78.53981633974483
}}
Sería extraño que el resultado del área fuera <code>0</code> debido a la definición anterior de <code>let r = 0</code>. Esto no sucede porque, la segunda vez que escribimos <code>r</code>, nos referimos a una <code>r</code> ''diferente''. Puede parecer confuso, pero piensa en lo siguiente: muchas personas se llaman Juan y, aun así, en una situación en la que solo hay un Juan presente, podemos decir «Juan» sin ninguna confusión. En programación, esta noción de contexto se denomina ''[[w:Ámbito (informática)|ámbito]]''.
No profundizaremos por ahora en los detalles técnicos relacionados con el ámbito, pero ten presente que el valor de un parámetro es exactamente el que se pasa a la función, independientemente del nombre que le hayas dado al definirla. Por lo tanto, elegir nombres apropiados para las variables ayuda considerablemente a que los seres humanos puedan leer el código.
== Resumen ==
# Las variables almacenan valores, que pueden ser cualquier expresión en Haskell.
# Las variables no cambian sus valores dentro de un mismo ámbito.
# Las funciones son útiles para escribir programas reutilizables.
# Las funciones pueden aceptar más de un parámetro.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
7l6o5mrnkr20qtz09a2izyqkngjs3fy
436509
436488
2026-10-14T12:58:59Z
Luciérnaga de conocimiento
119502
436509
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
''Todos los ejemplos de este capítulo pueden guardarse en un archivo y ejecutarse usando GHC. No incluyas `Prelude>` en ninguno de los ejemplos. Cuando aparezca este comando, significa que el código siguiente se ejecutó en GHCi. Cuando no aparezca el comando, basta con copiar el código completo.''
== Variables ==
En el capítulo anterior, usamos GHCi como una calculadora, algo que resulta práctico únicamente para cálculos breves. Para realizar cálculos más complejos y escribir un programa en Haskell, generalmente tenemos que seguir y comprobar los resultados intermedios.
Podemos hacerlo asignando nombres. A estos nombres los llamamos ''variables''. Cuando se ejecuta un programa, cada variable se sustituye por un ''valor'' al que hace referencia. Por ejemplo, considera lo siguiente:
{{Haskell/GHCi|1=
Prelude> 3.141592653 * 5^2
78.539816325
}}
Este fue el cálculo aproximado del área de un círculo de radio <code>5</code>, de acuerdo con la fórmula <math>A = \pi r^2</math>. Por supuesto, resulta bastante laborioso escribir todos los dígitos de <math>\pi \approx 3,141592653</math>, o incluso recordar los primeros cinco. Por eso, para evitar repeticiones, podemos hacer que la máquina recuerde estos valores una sola vez, de modo que podamos utilizarlos siempre que sea necesario. Esta abstracción nos permite concentrarnos en otras partes más importantes. En este ejemplo, Haskell ya dispone de una variable llamada <code>pi</code> que almacena más de 15 dígitos de <math>\pi</math>, lo que hace que el código sea más claro y, además, nos permite obtener resultados más precisos.
{{Haskell/GHCi|1=
Prelude> pi
3.141592653589793
Prelude> pi * 5^2
78.53981633974483
}}
Observa cómo la variable <code>pi</code> y su valor, <code>3.141592653589793</code>, se sustituyen mutuamente en los cálculos.
== Archivos de código en Haskell ==
Además de realizar cálculos ocasionalmente en GHCi, puedes guardar tu código en un archivo Haskell, que es un archivo de texto con la extensión <tt>.hs</tt>. Se recomienda utilizar un editor de texto diseñado para la programación (consulta el [[w:Editor de texto|artículo de Wikipedia sobre editores de texto]]). La gran mayoría de ellos permiten ''resaltar la sintaxis'', es decir, colorear el código fuente para facilitar su lectura. Vim y Emacs son dos opciones bastante populares entre los programadores.
Para mantener todo organizado, crea también un directorio nuevo (una carpeta) en tu computadora para guardar los archivos Haskell que vayas creando al resolver los ejercicios de este libro. Vamos, crea un directorio llamado <tt>HaskellWikibook</tt>, por ejemplo, y dentro de él un archivo llamado <tt>Varfun.hs</tt> que contenga el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5.0
</syntaxhighlight>
Este programa define la variable <code>r</code> con el valor <code>5.0</code>.
Nota: asegúrate de que no haya espacios en blanco al comienzo de las líneas, porque Haskell distingue los espacios de indentación.
Después, abre una terminal en el directorio <tt>HaskellWikibook</tt> que creaste, ejecuta GHCi y carga el archivo <tt>Varfun.hs</tt> usando el comando <code>:load</code>:
{{Haskell/GHCi|1=
Prelude> :load Varfun.hs
[1 of 1] Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
}}
Conviene saber que <code>:load</code> puede abreviarse como <code>:l</code>: <code>:l Varfun.hs</code>.
Si GHCi devuelve un error como <code>Could not find module 'Varfun.hs'</code>, significa que probablemente te encuentras en el directorio equivocado. Prueba el comando <code>:cd</code> para cambiar el directorio actual desde GHCi (por ejemplo, <code>:cd HaskellWikibook</code>).
Después de cargar el archivo en la sesión de GHCi, verás que la línea de comandos cambia de "Prelude" a "*Main". Ahora puedes utilizar la variable <code>r</code> que definiste en el archivo.
{{Haskell/GHCi|1=
*Main> r
5.0
*Main> pi * r^2
78.53981633974483
}}
Acabamos de calcular el área de un círculo de radio 5,0 utilizando la fórmula <math>\pi r^2</math>. Lo que hicimos fue utilizar <code>r</code>, que definimos en el archivo <tt>Varfun.hs</tt>, y <code>pi</code>, que ya está definida en otro lugar.
Ahora vamos a facilitar el acceso a este valor definiendo también un nombre para él. Abre nuevamente el archivo y cambia su contenido por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 5.0
area = pi * r ^ 2
</syntaxhighlight>
Guárdalo y vuelve a cargarlo en GHCi mediante <code>:reload</code>, o simplemente <code>:r</code>:
{{Haskell/GHCi|1=
*Main> :reload
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
}}
Ahora tenemos dos variables: <code>r</code> y <code>area</code>.
{{Haskell/GHCi|1=
*Main> area
78.53981633974483
*Main> area / r
15.707963267948966
}}
{{nota|La palabra <code>let</code> es la que deberíamos utilizar para definir nuevas variables directamente en GHCi, sin necesidad de editar un archivo de código. Aunque hacerlo de esta manera puede resultar práctico, no siempre es lo más conveniente para tareas complejas. En esos casos, es preferible utilizar archivos.}}
== Comentarios ==
Además del propio código, los archivos de código fuente pueden contener textos conocidos como ''comentarios'', que el compilador ignora. En Haskell existen dos tipos de comentarios. El primero comienza con <code>--</code> y se extiende hasta el final de la línea:
<syntaxhighlight lang = "haskell">
x = 5 -- x es 5.
y = 6 -- y es 6.
-- z = 7 -- z no está definida.
</syntaxhighlight>
En este caso, <code>x</code> e <code>y</code> están efectivamente definidas en el código, pero <code>z</code> no lo está.
El segundo tipo de comentario está delimitado por <code>{- ... -}</code> y puede abarcar varias líneas:
<syntaxhighlight lang = "haskell">
answer = 2 * {-
bloque de comentario de varias líneas y...
-} 3 {- comentario en medio de la línea -} * 7
</syntaxhighlight>
Los comentarios se utilizan para explicar partes de un programa o realizar anotaciones sobre cualquier aspecto del contexto. Es importante señalar que abusar de los comentarios puede, en realidad, dificultar la lectura del propio código. Además, los comentarios desactualizados también pueden generar confusiones.
== Variables en lenguajes imperativos ==
Los lectores familiarizados con los lenguajes de programación imperativos notarán que las variables en Haskell se comportan de manera muy diferente a las variables en C, por ejemplo.
Si no tienes experiencia previa en programación, puedes saltarte esta sección, aunque puede ayudarte a comprender las situaciones en las que se compara el comportamiento de Haskell con el de otros lenguajes. Muchos libros sobre Haskell lo hacen, por ejemplo.
La ''programación imperativa'' trata las variables como posiciones en la memoria de la computadora. Este enfoque está relacionado con el funcionamiento básico de una computadora. Los programas imperativos indican explícitamente a la computadora lo que debe hacer. Los lenguajes de alto nivel, aunque pueden estar bastante alejados de estos conceptos, todavía conservan parte de ellos en el sentido de que siguen utilizando este patrón de programación «paso a paso». En contraste, la ''programación funcional'' ofrece una manera diferente de pensar, utilizando términos matemáticos y dejando de lado las instrucciones directas a la computadora, que solo son traducidas por el compilador a algo que la máquina pueda interpretar y procesar.
Veamos un ejemplo. El siguiente código no funcionaría en Haskell:
<syntaxhighlight lang = "haskell">
r = 5
r = 2
</syntaxhighlight>
Un programador de lenguajes imperativos interpretaría esto como: primero, definir <code>r = 5</code> y después redefinirla como <code>r = 2</code>. En Haskell, sin embargo, el compilador respondería con un error: «múltiples declaraciones de <code>r</code>». Dentro de un ámbito determinado, una variable de Haskell se define una sola vez y su definición no puede cambiar.
Las variables de Haskell parecen ''invariables'', pero en realidad se comportan como variables matemáticas. En Matemáticas nunca vemos que una variable cambie de valor dentro de un mismo problema, y lo mismo sucede en Haskell.
Más precisamente, las variables de Haskell son ''inmutables'': sus valores solo varían de acuerdo con los datos que introducimos en el programa. No podemos definir <code>r</code> de dos maneras diferentes en un mismo código, pero podemos cambiar su valor modificando el archivo. Cambiemos el código anterior por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 2.0
area = pi * r ^ 2
</syntaxhighlight>
Por supuesto, funcionará. Hemos cambiado <code>r</code> en el único lugar donde está definida, y eso modifica su valor en el resto del programa.
En problemas reales, los programas en Haskell dejan ''algunos'' valores sin definir en el código. Esos valores se definen más adelante, cuando el programa obtiene datos de un archivo o de una acción externa. Por ahora, sin embargo, nos limitaremos a definir variables internamente. Aprenderemos sobre las interacciones con el mundo exterior en capítulos posteriores.
Veamos otro ejemplo de la gran diferencia entre Haskell y los lenguajes imperativos:
<syntaxhighlight lang = "haskell">
r = r + 1
</syntaxhighlight>
En lugar de «incrementar el valor de <code>r</code>», es decir, actualizar el valor almacenado en la memoria, este código en Haskell constituye una definición recursiva de <code>r</code>, o sea, la define en términos de sí misma. No te preocupes, pues explicaremos la [[Haskell/Recursión|recursión]] más adelante. En este caso concreto, si <code>r</code> ya hubiera sido definida con algún valor, el compilador devolvería un mensaje de error, como explicamos anteriormente. Si <code>r</code> se hubiera definido con el valor 5, escribir <code>r = r + 1</code> sería equivalente a intentar afirmar que <math>5 = 5 + 1</math> en Matemáticas, lo cual es evidentemente incorrecto.
Como los valores no cambian dentro de un mismo programa, las variables pueden definirse en el orden que queramos. Por ejemplo, los dos códigos siguientes son exactamente equivalentes:
{|border="0"
|-
||<syntaxhighlight lang = "haskell">
y = x * 2
x = 3
</syntaxhighlight>
||<syntaxhighlight lang = "haskell">
x = 3
y = x * 2
</syntaxhighlight>
|}
En Haskell no existe la noción de que «<code>x</code> se declaró antes que <code>y</code>», o viceversa. Por supuesto, para utilizar <code>y</code> seguimos necesitando el valor de <code>x</code>, pero el orden no nos importa, ni tampoco al compilador.
== Funciones ==
Modificar el programa cada vez que queramos calcular el área de un círculo diferente resulta tedioso y nos limita a un círculo por vez. Podríamos calcular dos áreas duplicando todos los cálculos en nuestro código y definiendo <code>r2</code> y <code>area2</code><ref group=nota>Podemos observar aquí que los nombres de las variables pueden contener números y letras. Sin embargo, toda variable ''debe'' comenzar con una letra minúscula, seguida de otras letras (también mayúsculas), números, guiones bajos (_) o apóstrofos (').</ref>
<syntaxhighlight lang = "haskell">
r = 5
area = pi * r ^ 2
r2 = 3
area2 = pi * r2 ^ 2
</syntaxhighlight>
Para evitar esta repetición constante, es preferible añadir simplemente una ''función'' para calcular el área y aplicarla a diferentes radios.
Una ''función'' recibe un ''argumento'' (o ''parámetro'') y devuelve un resultado, exactamente igual que en Matemáticas. En Haskell, las funciones se definen de la misma manera que las variables, salvo que debemos indicar sus argumentos en el lado izquierdo de la expresión. Por ejemplo, el siguiente código define <code>area</code>, cuyo argumento es <code>r</code>:
<syntaxhighlight lang = "haskell">
area r = pi * r ^ 2
</syntaxhighlight>
Observa la sintaxis: primero aparece el nombre de la función (<code>area</code>), seguido de un espacio en blanco y de su argumento (<code>r</code>). Después aparece el signo <code>=</code> y la definición de la función, que utiliza el argumento de entrada en su cálculo.
Ahora podemos probar diferentes valores del radio y ''llamar'' a la función con ellos. Guarda el código anterior en un archivo, ábrelo en GHCi y prueba lo siguiente:
{{Haskell/GHCi|1=
*Main> area 5
78.53981633974483
*Main> area 3
28.274333882308138
*Main> area 17
907.9202768874502
}}
Acabamos de ''llamar'' a la función con diferentes valores y hemos calculado las áreas de tres círculos distintos.
Matemáticamente, el cálculo del área puede representarse mediante <math>A(r) = \pi \cdot r ^ 2</math>. Para calcular las áreas, escribiríamos <math>A(5) = 78.54</math> o <math>A(3) = 28.27</math>. Haskell también permite utilizar paréntesis, pero por convención suelen omitirse para que el código tenga menos símbolos y sea más legible.
Aun así, los paréntesis se utilizan para agrupar ''expresiones'' (cualquier código que devuelva un valor) que deben calcularse en conjunto. Observa cómo se interpretan de manera diferente las siguientes expresiones:
<syntaxhighlight lang = "haskell">
5 * 3 + 2 -- 15 + 2 = 17 (la multiplicación se realiza antes que la suma)
5 * (3 + 2) -- 5 * 5 = 25 (los paréntesis obligan a calcular primero la suma)
area 5 * 3 -- (area 5) * 3
area (5 * 3) -- area 15
</syntaxhighlight>
Del mismo modo que la multiplicación se realiza antes que la suma, observa que las aplicaciones de funciones en Haskell tienen una precedencia mayor que cualquier operador, ya sea <code>+</code> o <code>*</code>, por ejemplo.
== Evaluación de expresiones ==
¿Qué sucede exactamente cuando introducimos una expresión en GHCi? Después de pulsar «Enter», se evalúa. Esto significa que cada función se sustituye por su definición y se realizan los cálculos hasta que queda un único valor final. Por ejemplo, al ejecutar <code>area 5</code>, sucede lo siguiente:
<syntaxhighlight lang=haskell>
area 5 -- todas las apariciones de 'r' a la derecha se sustituyen por '5'
pi * 5 ^ 2 -- 'pi' se sustituye por un valor aproximado
3.141592653589793 * 5 ^ 2 -- se realiza la operación de potenciación '5 ^ 2'
3.141592653589793 * 25 -- se realiza la operación de multiplicación
78.53981633974483 -- resultado final
</syntaxhighlight>
Cuando utilizamos GHCi, el resultado de ''aplicar'' o ''llamar'' a la función, siguiendo el procedimiento anterior, aparece en la pantalla.
Veamos ahora algunas funciones más:
<syntaxhighlight lang = "haskell">
duplicar x = 2 * x
cuadruplicar x = double (double x)
cuadrado x = x * x
mitad x = x / 2
</syntaxhighlight>
{{Haskell/Ejercicios|1=
* Explica cómo evaluaría GHCi <code>cuadruplicar 5</code>.
* Define una función que reste 12 a la mitad de su argumento.
}}
== Parámetros múltiples ==
Las funciones también pueden tener más de un argumento. Por ejemplo, para calcular el área de un rectángulo necesitamos su longitud y su anchura:
<syntaxhighlight lang = "haskell">
areaRectang a b = a * b
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaRectang 5 10
50
}}
Otro ejemplo es el área de un triángulo, <math>A = \frac{bh}{2}</math>:
<syntaxhighlight lang="haskell">
areaTriang b h = (b * h) / 2
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaTriang 3 9
13.5
}}
Como puedes ver, los argumentos se separan mediante espacios. Por eso, a veces es necesario utilizar paréntesis para agrupar expresiones. Por ejemplo, no podemos escribir el cuádruple de un valor de la siguiente manera:
<syntaxhighlight lang = "haskell">
cuadruple x = double double x -- error
</syntaxhighlight>
Esto aplicaría la función <code>double</code> a dos argumentos: <code>double</code> y <code>x</code>. Sí es posible que las ''funciones sean argumentos de otras funciones'', como veremos más adelante, pero eso no es lo que queremos hacer aquí. Para que esta función funcione, necesitamos utilizar paréntesis:
<syntaxhighlight lang = "haskell">
cuadruple x = double (double x)
</syntaxhighlight>
Los argumentos siempre se pasan en el orden en que aparecen. Por ejemplo:
<syntaxhighlight lang = "haskell">
menos x y = x - y
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> menos 10 5
5
*Main> menos 5 10
-5
}}
Aquí, <code>menos 10 5</code> evalúa la expresión <code>10 - 5</code>, mientras que <code>menos 5 10</code> evalúa <code>5 - 10</code>, debido al cambio en el orden de los argumentos.
{{Haskell/Ejercicios|1=
* Escribe una función para calcular el volumen de una caja.
* ¿Aproximadamente cuántas piedras se utilizaron para construir las famosas pirámides de Guiza? Pista: tendrás que estimar el volumen de la pirámide y el volumen de cada bloque de piedra.
}}
== Combinación de funciones ==
Por supuesto, puedes utilizar otras funciones para definir las tuyas, del mismo modo que ya lo has hecho utilizando la suma, <code>+</code>, o la multiplicación, <code>*</code>. De hecho, los operadores también se definen como funciones en Haskell. Por ejemplo, para calcular el área de un cuadrado, podemos reutilizar la función que calcula el área de un rectángulo:
<syntaxhighlight lang = "haskell">
areaRetang a b = a * b
areaCuad l = areaRetang l l
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaCuad 5
25
}}
Al fin y al cabo, un cuadrado es un rectángulo cuyos lados son iguales.
{{Haskell/Ejercicios|1=
* Escribe una función que calcule el volumen de un cilindro. El volumen de un cilindro es el área de su base, que es un círculo, multiplicada por la altura. Como ya has programado la función que calcula el área de un círculo en este capítulo, puedes reutilizarla aquí.
}}
== Definición de funciones locales ==
=== Uso de <code>where</code> ===
Cuando definimos una función, a veces necesitamos calcular valores intermedios que son ''locales'' y se utilizan únicamente dentro de esa función. Considera la [[w:teorema de Herón|fórmula de Herón]]: <math>A = \sqrt{p(p-a)(p-b)(p-c)}</math>, donde <math>p</math> es la mitad del perímetro del triángulo. Este es el cálculo del área de un triángulo cuyos lados miden <code>a</code>, <code>b</code> y <code>c</code>:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
where
s = (a + b + c) / 2
</syntaxhighlight>
La variable <code>s</code> representa la mitad del perímetro. Sería tedioso y propenso a errores tener que escribir <code>(a + b + c)/2</code> cada vez que necesitáramos este valor dentro de <code>herao</code>. <code>sqrt</code> calcula la raíz cuadrada de su argumento (recuerda que significa ''square root'' en inglés).
Escribir las definiciones por separado no funcionaría. Observa:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2 -- a, b y c no están definidas aquí
</syntaxhighlight>
El compilador señalaría que <code>a</code>, <code>b</code> y <code>c</code> solo están disponibles en el lado derecho de <code>herao</code>, mientras que la definición de <code>s</code> no forma parte del lado derecho de <code>herao</code>. Para incluirla allí, utilizamos la palabra clave <code>where</code>.
Observa que tanto <code>where</code> como la definición de <code>s</code> están indentadas con cuatro espacios en blanco. Esto es importante para delimitar qué pertenece a cada bloque. Veamos otros ejemplos del uso de <code>where</code>:
<syntaxhighlight lang = "haskell">
areaTriangTrig a b c = c * altura / 2 -- usando trigonometría
where
cosAlfa = (b ^ 2 + c ^ 2 - a ^ 2) / (2 * b * c)
sinAlfa = sqrt (1 - cosAlfa ^ 2)
altura = b * sinAlfa
areaTriangHeron a b c = resultado -- usa la fórmula de Herón
where
resultado = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2
</syntaxhighlight>
== Ámbito ==
Observa atentamente el ejemplo anterior: fíjate en que utilizamos las variables <code>a</code>, <code>b</code> y <code>c</code> dos veces, en cada una de las funciones definidas. ¿Cómo es posible?
Considera el siguiente procedimiento en GHCi:
{{Haskell/GHCi|1=
Prelude> let r = 0
Prelude> let area r = pi * r ^ 2
Prelude> area 5
78.53981633974483
}}
Sería extraño que el resultado del área fuera <code>0</code> debido a la definición anterior de <code>let r = 0</code>. Esto no sucede porque, la segunda vez que escribimos <code>r</code>, nos referimos a una <code>r</code> ''diferente''. Puede parecer confuso, pero piensa en lo siguiente: muchas personas se llaman Juan y, aun así, en una situación en la que solo hay un Juan presente, podemos decir «Juan» sin ninguna confusión. En programación, esta noción de contexto se denomina ''[[w:Ámbito (informática)|ámbito]]''.
No profundizaremos por ahora en los detalles técnicos relacionados con el ámbito, pero ten presente que el valor de un parámetro es exactamente el que se pasa a la función, independientemente del nombre que le hayas dado al definirla. Por lo tanto, elegir nombres apropiados para las variables ayuda considerablemente a que los seres humanos puedan leer el código.
== Resumen ==
# Las variables almacenan valores, que pueden ser cualquier expresión en Haskell.
# Las variables no cambian sus valores dentro de un mismo ámbito.
# Las funciones son útiles para escribir programas reutilizables.
# Las funciones pueden aceptar más de un parámetro.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
bez4b7lsww81s83bzrxsw28zqlehlbz
436513
436509
2026-10-14T13:06:53Z
Luciérnaga de conocimiento
119502
436513
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Variables y funciones|título=Principios básicos de Haskell|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
''Todos los ejemplos de este capítulo pueden guardarse en un archivo y ejecutarse usando GHC. No incluyas `Prelude>` en ninguno de los ejemplos. Cuando aparezca este comando, significa que el código siguiente se ejecutó en GHCi. Cuando no aparezca el comando, basta con copiar el código completo.''
== Variables ==
En el capítulo anterior, usamos GHCi como una calculadora, algo que resulta práctico únicamente para cálculos breves. Para realizar cálculos más complejos y escribir un programa en Haskell, generalmente tenemos que seguir y comprobar los resultados intermedios.
Podemos hacerlo asignando nombres. A estos nombres los llamamos ''variables''. Cuando se ejecuta un programa, cada variable se sustituye por un ''valor'' al que hace referencia. Por ejemplo, considera lo siguiente:
{{Haskell/GHCi|1=
Prelude> 3.141592653 * 5^2
78.539816325
}}
Este fue el cálculo aproximado del área de un círculo de radio <code>5</code>, de acuerdo con la fórmula <math>A = \pi r^2</math>. Por supuesto, resulta bastante laborioso escribir todos los dígitos de <math>\pi \approx 3,141592653</math>, o incluso recordar los primeros cinco. Por eso, para evitar repeticiones, podemos hacer que la máquina recuerde estos valores una sola vez, de modo que podamos utilizarlos siempre que sea necesario. Esta abstracción nos permite concentrarnos en otras partes más importantes. En este ejemplo, Haskell ya dispone de una variable llamada <code>pi</code> que almacena más de 15 dígitos de <math>\pi</math>, lo que hace que el código sea más claro y, además, nos permite obtener resultados más precisos.
{{Haskell/GHCi|1=
Prelude> pi
3.141592653589793
Prelude> pi * 5^2
78.53981633974483
}}
Observa cómo la variable <code>pi</code> y su valor, <code>3.141592653589793</code>, se sustituyen mutuamente en los cálculos.
== Archivos de código en Haskell ==
Además de realizar cálculos ocasionalmente en GHCi, puedes guardar tu código en un archivo Haskell, que es un archivo de texto con la extensión <tt>.hs</tt>. Se recomienda utilizar un editor de texto diseñado para la programación (consulta el [[w:Editor de texto|artículo de Wikipedia sobre editores de texto]]). La gran mayoría de ellos permiten ''resaltar la sintaxis'', es decir, colorear el código fuente para facilitar su lectura. Vim y Emacs son dos opciones bastante populares entre los programadores.
Para mantener todo organizado, crea también un directorio nuevo (una carpeta) en tu computadora para guardar los archivos Haskell que vayas creando al resolver los ejercicios de este libro. Vamos, crea un directorio llamado <tt>HaskellWikibook</tt>, por ejemplo, y dentro de él un archivo llamado <tt>Varfun.hs</tt> que contenga el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5.0
</syntaxhighlight>
Este programa define la variable <code>r</code> con el valor <code>5.0</code>.
Nota: asegúrate de que no haya espacios en blanco al comienzo de las líneas, porque Haskell distingue los espacios de indentación.
Después, abre una terminal en el directorio <tt>HaskellWikibook</tt> que creaste, ejecuta GHCi y carga el archivo <tt>Varfun.hs</tt> usando el comando <code>:load</code>:
{{Haskell/GHCi|1=
Prelude> :load Varfun.hs
[1 of 1] Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
}}
Conviene saber que <code>:load</code> puede abreviarse como <code>:l</code>: <code>:l Varfun.hs</code>.
Si GHCi devuelve un error como <code>Could not find module 'Varfun.hs'</code>, significa que probablemente te encuentras en el directorio equivocado. Prueba el comando <code>:cd</code> para cambiar el directorio actual desde GHCi (por ejemplo, <code>:cd HaskellWikibook</code>).
Después de cargar el archivo en la sesión de GHCi, verás que la línea de comandos cambia de "Prelude" a "*Main". Ahora puedes utilizar la variable <code>r</code> que definiste en el archivo.
{{Haskell/GHCi|1=
*Main> r
5.0
*Main> pi * r^2
78.53981633974483
}}
Acabamos de calcular el área de un círculo de radio 5,0 utilizando la fórmula <math>\pi r^2</math>. Lo que hicimos fue utilizar <code>r</code>, que definimos en el archivo <tt>Varfun.hs</tt>, y <code>pi</code>, que ya está definida en otro lugar.
Ahora vamos a facilitar el acceso a este valor definiendo también un nombre para él. Abre nuevamente el archivo y cambia su contenido por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 5.0
area = pi * r ^ 2
</syntaxhighlight>
Guárdalo y vuelve a cargarlo en GHCi mediante <code>:reload</code>, o simplemente <code>:r</code>:
{{Haskell/GHCi|1=
*Main> :reload
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
}}
Ahora tenemos dos variables: <code>r</code> y <code>area</code>.
{{Haskell/GHCi|1=
*Main> area
78.53981633974483
*Main> area / r
15.707963267948966
}}
{{nota|La palabra <code>let</code> es la que deberíamos utilizar para definir nuevas variables directamente en GHCi, sin necesidad de editar un archivo de código. Aunque hacerlo de esta manera puede resultar práctico, no siempre es lo más conveniente para tareas complejas. En esos casos, es preferible utilizar archivos.}}
== Comentarios ==
Además del propio código, los archivos de código fuente pueden contener textos conocidos como ''comentarios'', que el compilador ignora. En Haskell existen dos tipos de comentarios. El primero comienza con <code>--</code> y se extiende hasta el final de la línea:
<syntaxhighlight lang = "haskell">
x = 5 -- x es 5.
y = 6 -- y es 6.
-- z = 7 -- z no está definida.
</syntaxhighlight>
En este caso, <code>x</code> e <code>y</code> están efectivamente definidas en el código, pero <code>z</code> no lo está.
El segundo tipo de comentario está delimitado por <code>{- ... -}</code> y puede abarcar varias líneas:
<syntaxhighlight lang = "haskell">
answer = 2 * {-
bloque de comentario de varias líneas y...
-} 3 {- comentario en medio de la línea -} * 7
</syntaxhighlight>
Los comentarios se utilizan para explicar partes de un programa o realizar anotaciones sobre cualquier aspecto del contexto. Es importante señalar que abusar de los comentarios puede, en realidad, dificultar la lectura del propio código. Además, los comentarios desactualizados también pueden generar confusiones.
== Variables en lenguajes imperativos ==
Los lectores familiarizados con los lenguajes de programación imperativos notarán que las variables en Haskell se comportan de manera muy diferente a las variables en C, por ejemplo.
Si no tienes experiencia previa en programación, puedes saltarte esta sección, aunque puede ayudarte a comprender las situaciones en las que se compara el comportamiento de Haskell con el de otros lenguajes. Muchos libros sobre Haskell lo hacen, por ejemplo.
La ''programación imperativa'' trata las variables como posiciones en la memoria de la computadora. Este enfoque está relacionado con el funcionamiento básico de una computadora. Los programas imperativos indican explícitamente a la computadora lo que debe hacer. Los lenguajes de alto nivel, aunque pueden estar bastante alejados de estos conceptos, todavía conservan parte de ellos en el sentido de que siguen utilizando este patrón de programación «paso a paso». En contraste, la ''programación funcional'' ofrece una manera diferente de pensar, utilizando términos matemáticos y dejando de lado las instrucciones directas a la computadora, que solo son traducidas por el compilador a algo que la máquina pueda interpretar y procesar.
Veamos un ejemplo. El siguiente código no funcionaría en Haskell:
<syntaxhighlight lang = "haskell">
r = 5
r = 2
</syntaxhighlight>
Un programador de lenguajes imperativos interpretaría esto como: primero, definir <code>r = 5</code> y después redefinirla como <code>r = 2</code>. En Haskell, sin embargo, el compilador respondería con un error: «múltiples declaraciones de <code>r</code>». Dentro de un ámbito determinado, una variable de Haskell se define una sola vez y su definición no puede cambiar.
Las variables de Haskell parecen ''invariables'', pero en realidad se comportan como variables matemáticas. En Matemáticas nunca vemos que una variable cambie de valor dentro de un mismo problema, y lo mismo sucede en Haskell.
Más precisamente, las variables de Haskell son ''inmutables'': sus valores solo varían de acuerdo con los datos que introducimos en el programa. No podemos definir <code>r</code> de dos maneras diferentes en un mismo código, pero podemos cambiar su valor modificando el archivo. Cambiemos el código anterior por lo siguiente:
<syntaxhighlight lang = "haskell">
r = 2.0
area = pi * r ^ 2
</syntaxhighlight>
Por supuesto, funcionará. Hemos cambiado <code>r</code> en el único lugar donde está definida, y eso modifica su valor en el resto del programa.
En problemas reales, los programas en Haskell dejan ''algunos'' valores sin definir en el código. Esos valores se definen más adelante, cuando el programa obtiene datos de un archivo o de una acción externa. Por ahora, sin embargo, nos limitaremos a definir variables internamente. Aprenderemos sobre las interacciones con el mundo exterior en capítulos posteriores.
Veamos otro ejemplo de la gran diferencia entre Haskell y los lenguajes imperativos:
<syntaxhighlight lang = "haskell">
r = r + 1
</syntaxhighlight>
En lugar de «incrementar el valor de <code>r</code>», es decir, actualizar el valor almacenado en la memoria, este código en Haskell constituye una definición recursiva de <code>r</code>, o sea, la define en términos de sí misma. No te preocupes, pues explicaremos la [[Haskell/Recursión|recursión]] más adelante. En este caso concreto, si <code>r</code> ya hubiera sido definida con algún valor, el compilador devolvería un mensaje de error, como explicamos anteriormente. Si <code>r</code> se hubiera definido con el valor 5, escribir <code>r = r + 1</code> sería equivalente a intentar afirmar que <math>5 = 5 + 1</math> en Matemáticas, lo cual es evidentemente incorrecto.
Como los valores no cambian dentro de un mismo programa, las variables pueden definirse en el orden que queramos. Por ejemplo, los dos códigos siguientes son exactamente equivalentes:
{|border="0"
|-
||<syntaxhighlight lang = "haskell">
y = x * 2
x = 3
</syntaxhighlight>
||<syntaxhighlight lang = "haskell">
x = 3
y = x * 2
</syntaxhighlight>
|}
En Haskell no existe la noción de que «<code>x</code> se declaró antes que <code>y</code>», o viceversa. Por supuesto, para utilizar <code>y</code> seguimos necesitando el valor de <code>x</code>, pero el orden no nos importa, ni tampoco al compilador.
== Funciones ==
Modificar el programa cada vez que queramos calcular el área de un círculo diferente resulta tedioso y nos limita a un círculo por vez. Podríamos calcular dos áreas duplicando todos los cálculos en nuestro código y definiendo <code>r2</code> y <code>area2</code><ref group=nota>Podemos observar aquí que los nombres de las variables pueden contener números y letras. Sin embargo, toda variable ''debe'' comenzar con una letra minúscula, seguida de otras letras (también mayúsculas), números, guiones bajos (_) o apóstrofos (').</ref>
<syntaxhighlight lang = "haskell">
r = 5
area = pi * r ^ 2
r2 = 3
area2 = pi * r2 ^ 2
</syntaxhighlight>
Para evitar esta repetición constante, es preferible añadir simplemente una ''función'' para calcular el área y aplicarla a diferentes radios.
Una ''función'' recibe un ''argumento'' (o ''parámetro'') y devuelve un resultado, exactamente igual que en Matemáticas. En Haskell, las funciones se definen de la misma manera que las variables, salvo que debemos indicar sus argumentos en el lado izquierdo de la expresión. Por ejemplo, el siguiente código define <code>area</code>, cuyo argumento es <code>r</code>:
<syntaxhighlight lang = "haskell">
area r = pi * r ^ 2
</syntaxhighlight>
Observa la sintaxis: primero aparece el nombre de la función (<code>area</code>), seguido de un espacio en blanco y de su argumento (<code>r</code>). Después aparece el signo <code>=</code> y la definición de la función, que utiliza el argumento de entrada en su cálculo.
Ahora podemos probar diferentes valores del radio y ''llamar'' a la función con ellos. Guarda el código anterior en un archivo, ábrelo en GHCi y prueba lo siguiente:
{{Haskell/GHCi|1=
*Main> area 5
78.53981633974483
*Main> area 3
28.274333882308138
*Main> area 17
907.9202768874502
}}
Acabamos de ''llamar'' a la función con diferentes valores y hemos calculado las áreas de tres círculos distintos.
Matemáticamente, el cálculo del área puede representarse mediante <math>A(r) = \pi \cdot r ^ 2</math>. Para calcular las áreas, escribiríamos <math>A(5) = 78.54</math> o <math>A(3) = 28.27</math>. Haskell también permite utilizar paréntesis, pero por convención suelen omitirse para que el código tenga menos símbolos y sea más legible.
Aun así, los paréntesis se utilizan para agrupar ''expresiones'' (cualquier código que devuelva un valor) que deben calcularse en conjunto. Observa cómo se interpretan de manera diferente las siguientes expresiones:
<syntaxhighlight lang = "haskell">
5 * 3 + 2 -- 15 + 2 = 17 (la multiplicación se realiza antes que la suma)
5 * (3 + 2) -- 5 * 5 = 25 (los paréntesis obligan a calcular primero la suma)
area 5 * 3 -- (area 5) * 3
area (5 * 3) -- area 15
</syntaxhighlight>
Del mismo modo que la multiplicación se realiza antes que la suma, observa que las aplicaciones de funciones en Haskell tienen una precedencia mayor que cualquier operador, ya sea <code>+</code> o <code>*</code>, por ejemplo.
== Evaluación de expresiones ==
¿Qué sucede exactamente cuando introducimos una expresión en GHCi? Después de pulsar «Enter», se evalúa. Esto significa que cada función se sustituye por su definición y se realizan los cálculos hasta que queda un único valor final. Por ejemplo, al ejecutar <code>area 5</code>, sucede lo siguiente:
<syntaxhighlight lang=haskell>
area 5 -- todas las apariciones de 'r' a la derecha se sustituyen por '5'
pi * 5 ^ 2 -- 'pi' se sustituye por un valor aproximado
3.141592653589793 * 5 ^ 2 -- se realiza la operación de potenciación '5 ^ 2'
3.141592653589793 * 25 -- se realiza la operación de multiplicación
78.53981633974483 -- resultado final
</syntaxhighlight>
Cuando utilizamos GHCi, el resultado de ''aplicar'' o ''llamar'' a la función, siguiendo el procedimiento anterior, aparece en la pantalla.
Veamos ahora algunas funciones más:
<syntaxhighlight lang = "haskell">
duplicar x = 2 * x
cuadruplicar x = double (double x)
cuadrado x = x * x
mitad x = x / 2
</syntaxhighlight>
{{Haskell/Ejercicios|1=
* Explica cómo evaluaría GHCi <code>cuadruplicar 5</code>.
* Define una función que reste 12 a la mitad de su argumento.
}}
== Parámetros múltiples ==
Las funciones también pueden tener más de un argumento. Por ejemplo, para calcular el área de un rectángulo necesitamos su longitud y su anchura:
<syntaxhighlight lang = "haskell">
areaRectang a b = a * b
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaRectang 5 10
50
}}
Otro ejemplo es el área de un triángulo, <math>A = \frac{bh}{2}</math>:
<syntaxhighlight lang="haskell">
areaTriang b h = (b * h) / 2
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaTriang 3 9
13.5
}}
Como puedes ver, los argumentos se separan mediante espacios. Por eso, a veces es necesario utilizar paréntesis para agrupar expresiones. Por ejemplo, no podemos escribir el cuádruple de un valor de la siguiente manera:
<syntaxhighlight lang = "haskell">
cuadruple x = double double x -- error
</syntaxhighlight>
Esto aplicaría la función <code>double</code> a dos argumentos: <code>double</code> y <code>x</code>. Sí es posible que las ''funciones sean argumentos de otras funciones'', como veremos más adelante, pero eso no es lo que queremos hacer aquí. Para que esta función funcione, necesitamos utilizar paréntesis:
<syntaxhighlight lang = "haskell">
cuadruple x = double (double x)
</syntaxhighlight>
Los argumentos siempre se pasan en el orden en que aparecen. Por ejemplo:
<syntaxhighlight lang = "haskell">
menos x y = x - y
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> menos 10 5
5
*Main> menos 5 10
-5
}}
Aquí, <code>menos 10 5</code> evalúa la expresión <code>10 - 5</code>, mientras que <code>menos 5 10</code> evalúa <code>5 - 10</code>, debido al cambio en el orden de los argumentos.
{{Haskell/Ejercicios|1=
* Escribe una función para calcular el volumen de una caja.
* ¿Aproximadamente cuántas piedras se utilizaron para construir las famosas pirámides de Guiza? Pista: tendrás que estimar el volumen de la pirámide y el volumen de cada bloque de piedra.
}}
== Combinación de funciones ==
Por supuesto, puedes utilizar otras funciones para definir las tuyas, del mismo modo que ya lo has hecho utilizando la suma, <code>+</code>, o la multiplicación, <code>*</code>. De hecho, los operadores también se definen como funciones en Haskell. Por ejemplo, para calcular el área de un cuadrado, podemos reutilizar la función que calcula el área de un rectángulo:
<syntaxhighlight lang = "haskell">
areaRetang a b = a * b
areaCuad l = areaRetang l l
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaCuad 5
25
}}
Al fin y al cabo, un cuadrado es un rectángulo cuyos lados son iguales.
{{Haskell/Ejercicios|1=
* Escribe una función que calcule el volumen de un cilindro. El volumen de un cilindro es el área de su base, que es un círculo, multiplicada por la altura. Como ya has programado la función que calcula el área de un círculo en este capítulo, puedes reutilizarla aquí.
}}
== Definición de funciones locales ==
=== Uso de <code>where</code> ===
Cuando definimos una función, a veces necesitamos calcular valores intermedios que son ''locales'' y se utilizan únicamente dentro de esa función. Considera la [[w:teorema de Herón|fórmula de Herón]]: <math>A = \sqrt{p(p-a)(p-b)(p-c)}</math>, donde <math>p</math> es la mitad del perímetro del triángulo. Este es el cálculo del área de un triángulo cuyos lados miden <code>a</code>, <code>b</code> y <code>c</code>:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
where
s = (a + b + c) / 2
</syntaxhighlight>
La variable <code>s</code> representa la mitad del perímetro. Sería tedioso y propenso a errores tener que escribir <code>(a + b + c)/2</code> cada vez que necesitáramos este valor dentro de <code>herao</code>. <code>sqrt</code> calcula la raíz cuadrada de su argumento (recuerda que significa ''square root'' en inglés).
Escribir las definiciones por separado no funcionaría. Observa:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2 -- a, b y c no están definidas aquí
</syntaxhighlight>
El compilador señalaría que <code>a</code>, <code>b</code> y <code>c</code> solo están disponibles en el lado derecho de <code>herao</code>, mientras que la definición de <code>s</code> no forma parte del lado derecho de <code>herao</code>. Para incluirla allí, utilizamos la palabra clave <code>where</code>.
Observa que tanto <code>where</code> como la definición de <code>s</code> están indentadas con cuatro espacios en blanco. Esto es importante para delimitar qué pertenece a cada bloque. Veamos otros ejemplos del uso de <code>where</code>:
<syntaxhighlight lang = "haskell">
areaTriangTrig a b c = c * altura / 2 -- usando trigonometría
where
cosAlfa = (b ^ 2 + c ^ 2 - a ^ 2) / (2 * b * c)
sinAlfa = sqrt (1 - cosAlfa ^ 2)
altura = b * sinAlfa
areaTriangHeron a b c = resultado -- usa la fórmula de Herón
where
resultado = sqrt (p * (p - a) * (p - b) * (p - c))
p = (a + b + c) / 2
</syntaxhighlight>
== Ámbito ==
Observa atentamente el ejemplo anterior: fíjate en que utilizamos las variables <code>a</code>, <code>b</code> y <code>c</code> dos veces, en cada una de las funciones definidas. ¿Cómo es posible?
Considera el siguiente procedimiento en GHCi:
{{Haskell/GHCi|1=
Prelude> let r = 0
Prelude> let area r = pi * r ^ 2
Prelude> area 5
78.53981633974483
}}
Sería extraño que el resultado del área fuera <code>0</code> debido a la definición anterior de <code>let r = 0</code>. Esto no sucede porque, la segunda vez que escribimos <code>r</code>, nos referimos a una <code>r</code> ''diferente''. Puede parecer confuso, pero piensa en lo siguiente: muchas personas se llaman Juan y, aun así, en una situación en la que solo hay un Juan presente, podemos decir «Juan» sin ninguna confusión. En programación, esta noción de contexto se denomina ''[[w:Ámbito (informática)|ámbito]]''.
No profundizaremos por ahora en los detalles técnicos relacionados con el ámbito, pero ten presente que el valor de un parámetro es exactamente el que se pasa a la función, independientemente del nombre que le hayas dado al definirla. Por lo tanto, elegir nombres apropiados para las variables ayuda considerablemente a que los seres humanos puedan leer el código.
== Resumen ==
# Las variables almacenan valores, que pueden ser cualquier expresión en Haskell.
# Las variables no cambian sus valores dentro de un mismo ámbito.
# Las funciones son útiles para escribir programas reutilizables.
# Las funciones pueden aceptar más de un parámetro.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
egiedf10xnqs79y8kf6d5xpkltww0fl
Plantilla:Haskell/GHCi
10
64936
436497
436311
2026-10-14T12:32:41Z
Luciérnaga de conocimiento
119502
436497
wikitext
text/x-wiki
{{#tag:pre|{{{1}}}}}<noinclude>
<!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentación|content=This template is used for GHCi transcripts in Haskell books.}}
The <code>{{!}}1=</code> es necesario, ya que el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>
{{AutoCat}}
</noinclude>
gcreidprhybowtk9n9nkh93chd4t0es
436519
436497
2026-10-14T13:23:40Z
Luciérnaga de conocimiento
119502
436519
wikitext
text/x-wiki
{{#tag:pre|{{{1}}}}}<noinclude>
<!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentación|content=This template is used for GHCi transcripts in Haskell books.}}
The <code>{{!}}1=</code> es necesario, ya que el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>
[[Categoría:Libro:Plantillas:Haskell]]
{{AutoCat}}
</noinclude>
rcnv1snn756vc7q7jn51en7fy4pqugt
436520
436519
2026-10-14T13:24:46Z
Luciérnaga de conocimiento
119502
436520
wikitext
text/x-wiki
{{#tag:pre|{{{1}}}}}<noinclude>
<!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentación|content=This template is used for GHCi transcripts in Haskell books.}}
The <code>{{!}}1=</code> es necesario, ya que el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>
[[Category:Libro:Plantillas:Haskell]]
{{AutoCat}}
</noinclude>
rjvei6kel9g2o5savdu7bf9qqvwza70
436521
436520
2026-10-14T13:24:57Z
Luciérnaga de conocimiento
119502
436521
wikitext
text/x-wiki
{{#tag:pre|{{{1}}}}}<noinclude>
<!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentación|content=This template is used for GHCi transcripts in Haskell books.}}
The <code>{{!}}1=</code> es necesario, ya que el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>
{{AutoCat}}
</noinclude>
gcreidprhybowtk9n9nkh93chd4t0es
436522
436521
2026-10-14T13:27:16Z
Luciérnaga de conocimiento
119502
436522
wikitext
text/x-wiki
{{#tag:pre|{{{1}}}}}<noinclude>
<!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentación|content=This template is used for GHCi transcripts in Haskell books.}}
The <code>{{!}}1=</code> es necesario, ya que el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>
[[Categoría:Libro:Plantillas:Haskell]]
</noinclude>
os8v3hhz9g355ssiylm75btg1cbfjz0
Categoría:Libro:Plantillas:Haskell
14
64937
436491
435938
2026-10-14T12:19:04Z
Luciérnaga de conocimiento
119502
Luciérnaga de conocimiento trasladó la página [[Categoría:Libro:Plantilla:Haskell]] a [[Categoría:Libro:Plantillas:Haskell]]
435938
wikitext
text/x-wiki
[[Categoría:Libro:Haskell]]
ru8trst303x18blgxzh6eb563blck26
Plantilla:Haskell/GHCi/uso
10
64938
436498
435944
2026-10-14T12:33:35Z
Luciérnaga de conocimiento
119502
436498
wikitext
text/x-wiki
{{subpágina de documentación}}
=== Uso ===
<!-- Explica para qué sirve la plantilla, cuándo debe utilizarse y el propósito de cada parámetro, si los tiene. -->
Ejemplo:
<pre><nowiki>
{{Haskell/GHCi|1=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Se muestra como:
{{Haskell/GHCi|1=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
El <code>{{!}}1=</code> es necesario porque el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>.
{{AutoCat}}</noinclude>
kowuvwd3lmvaaolic0em3x7iz6cxe17
436523
436498
2026-10-14T13:27:35Z
Luciérnaga de conocimiento
119502
436523
wikitext
text/x-wiki
{{subpágina de documentación}}
=== Uso ===
<!-- Explica para qué sirve la plantilla, cuándo debe utilizarse y el propósito de cada parámetro, si los tiene. -->
Ejemplo:
<pre><nowiki>
{{Haskell/GHCi|1=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Se muestra como:
{{Haskell/GHCi|1=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
El <code>{{!}}1=</code> es necesario porque el texto puede contener signos de igualdad. De lo contrario, solo se mostraría <code>{{{1}}}</code>.
8dexcw259qqa065vmv9wjuw9ytw8u7p
Haskell/Valores de verdad
0
65076
436500
436377
2026-10-14T12:37:08Z
Luciérnaga de conocimiento
119502
436500
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad}}
== Igualdad y otras comparaciones ==
En el capítulo anterior, usamos signos de igualdad para definir variables y funciones en Haskell, como se muestra en el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
Esto significa que, durante la evaluación del programa, todas las apariciones de <code>r</code> se sustituyen por <code>5</code> dentro del mismo ámbito. De manera similar, al evaluar
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
todas las apariciones de <code>f</code> seguidas de un número (el argumento de <code>f</code>) se sustituyen por ese valor más tres.
En Matemáticas, el signo de igualdad se usa de manera diferente. Consideremos el siguiente problema:
{{Haskell/Ejercicios|1=
Resuelve el siguiente problema: <math>x+3=5</math>.
}}
En este caso, el problema no consiste en representar <math>5</math> como si fuera <math>x+3</math>, o viceversa. En realidad, tenemos una ''proposición'' que afirma que un número <math>x</math>, al sumarle 3, da como resultado 5. Resolver la ecuación significa encontrar el valor de <math>x</math>, si existe alguno, que haga verdadera la proposición. En este sencillo ejemplo, una simple manipulación algebraica nos muestra que <math>x=2</math>, es decir, <math>2</math> es el número que satisface la proposición, ya que <math>2+3=5</math>.
Comparar valores para comprobar si son iguales resulta bastante útil en programación. De hecho, es algo muy elemental y necesario. En Haskell, estas pruebas se parecen bastante a una ecuación. Sin embargo, como el signo igual ya se utiliza para definir algo, Haskell emplea un signo de igualdad ''doble'', <code>==</code>, para realizar comparaciones. Veamos:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
Aquí, GHCi devuelve <code>True</code> (''verdadero'', en inglés) porque <math>2 + 3</math> es igual a <math>5</math>. ¿Y si la ecuación no fuera verdadera?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
El resultado es <code>False</code> (''falso'', en inglés). Ahora vamos a utilizar la función <code>f</code> que definimos al comienzo de este capítulo:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
Como era de esperar. Puesto que <code>f 2</code> se evalúa como <code>2 + 3</code>, cuyo resultado es <code>5</code>, lo lógico es que <code>5 == 5</code> devuelva <code>True</code>.
También podemos comparar dos valores numéricos para averiguar cuál es mayor. Haskell dispone de varios operadores para estas pruebas: <code><</code>, para ''menor que''; <code>></code>, para ''mayor que''; <code><=</code>, para ''menor o igual que''; y <code>>=</code>, para ''mayor o igual que''. Estas pruebas funcionan exactamente igual que <code>==</code>, que significa ''igual a''. Por ejemplo, podríamos utilizar <code><</code> junto con la función <code>area</code> del capítulo anterior para comprobar si un círculo de cierto radio tiene un área menor que otro valor.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Valores booleanos ==
¿Qué sucede cuando GHCi tiene que determinar si estas comparaciones son verdaderas o falsas? Consideremos un caso diferente. Si introducimos una expresión aritmética en GHCi, esta se ''evalúa'' y el resultado numérico aparece en pantalla:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
Si sustituimos la expresión aritmética por su valor final en una comparación, sucede algo parecido:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Mientras que el «4» devuelto en el primer caso representa el recuento de alguna cosa, «True» es un ''valor'' que representa la verdad de una determinada proposición. Estos valores se conocen como '''booleanos'''.<ref group=nota>Este término se eligió en homenaje al matemático británico [[w:George Boole|George Boole]].</ref> Naturalmente, solo hay dos valores posibles, que ya se nos han presentado: <code>True</code> y <code>False</code>.
== Introducción a los tipos de datos ==
<code>True</code> y <code>False</code> son valores reales, no una simple analogía. En Haskell, los valores booleanos tienen el mismo ''estatus'' que los valores numéricos, y podemos manipularlos de manera similar. Veamos un ejemplo sencillo:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
En efecto, <code>True</code> es igual a <code>True</code>, y <code>True</code> no es igual a <code>False</code>. Ahora bien, ¿es posible determinar si <code>2</code> es igual a <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
El compilador produce un error. En realidad, la pregunta original ni siquiera tiene sentido. No se puede comparar un número con algo que no es un número, ni un valor booleano con algo que no es booleano. Haskell incorpora esta noción en el propio lenguaje, y el mensaje de error anterior, aunque es largo y un poco intimidante, expresa precisamente eso: a la izquierda de <code>==</code> hay un número (<code>Num</code>), por lo que se esperaba también un número a la derecha. Sin embargo, un valor booleano (<code>Bool</code>) no es un número, de modo que la prueba de igualdad falla.
Queda claro, entonces, que los valores se agrupan en '''tipos''', que establecen los límites de lo que podemos o no hacer con ellos. <code>True</code> y <code>False</code> son valores del tipo <code>Bool</code>. El caso de <code>2</code> es algo más complicado, porque en informática existen varios tipos de números, al igual que en Matemáticas, aunque no sean equivalentes. Pero, en definitiva, sigue siendo un dato numérico (<code>Num</code>). En general, esta característica restrictiva resulta muy valiosa, porque podemos aprovecharla para controlar el comportamiento de nuestros programas y establecer reglas que impidan utilizarlos con tipos de datos que ''no tienen sentido''. De este modo, garantizamos el funcionamiento correcto de lo que desarrollamos. Volveremos a tratar los tipos más adelante, ya que constituyen una parte importante del lenguaje Haskell.
== Operadores infijos ==
Una prueba de igualdad, como <code>2 == 2</code>, también es una expresión, al igual que una operación aritmética, como <code>2 + 2</code>. Ambos casos se evalúan básicamente de la misma manera. Cuando escribimos <code>2 == 2</code> en una sesión de GHCi, este «responde» con <code>True</code>, porque simplemente ha evaluado la expresión. En realidad, el operador <code>==</code> es una función de dos argumentos (el de la izquierda y el de la derecha de la igualdad). Sin embargo, su uso es diferente: Haskell permite escribir las funciones de dos argumentos como ''operadores infijos'', es decir, situados ''entre'' sus dos argumentos. Cuando el nombre de una función está formado por caracteres no alfanuméricos (<code>==</code>, por ejemplo), utilizarla como operador infijo es la forma más habitual. Si queremos utilizarla de la manera convencional, es decir, como un ''operador prefijo'' (con el nombre de la función antes de los argumentos), debemos encerrarla entre paréntesis. Veamos:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
También es posible transformar un valor booleano en otro mediante la ''negación''. <code>not</code> es la función de negación: transforma <code>True</code> en <code>False</code>, y <code>False</code> en <code>True</code>.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell ya dispone del operador de desigualdad: <code>/=</code>, que significa ''no es igual a''. Sin embargo, podríamos definirlo fácilmente mediante <code>not</code> y <code>==</code>:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Observa que podemos utilizar la notación de operadores infijos incluso al definirlos. Además, un operador puede definirse a partir de cualquier símbolo [[w:ASCII|ASCII]].
=== Otras operaciones booleanas ===
Existen otras operaciones booleanas muy útiles y necesarias: ''o'' e ''y''.
La operación ''A o B'' da como resultado verdadero si ''A'', ''B'' o ambos son verdaderos. En Haskell se representa mediante el operador <code>(||)</code>:
{{Haskell/GHCi|1=
Prelude> True {{!!}} True
True
Prelude> True {{!!}} False
True
Prelude> False {{!!}} True
True
Prelude> False {{!!}} False
False
}}
La operación ''A y B'' da como resultado verdadero si ''A'' y ''B'' son verdaderos. En Haskell se representa mediante el operador <code>(&&)</code>:
{{Haskell/GHCi|1=
Prelude> True && True
True
Prelude> True && False
False
Prelude> False && True
False
Prelude> False && False
False
}}
== Guardas ==
Los programas escritos en Haskell suelen utilizar operadores booleanos mediante una sintaxis muy cómoda y abreviada. Cuando una misma lógica se expresa con una sintaxis diferente, hablamos de [[w:Azúcar sintáctico|''azúcar sintáctico'']]. Esto significa que el código resulta más «agradable al paladar humano». Conviene recordar este término, porque aparece con frecuencia en los materiales sobre Haskell.
Uno de estos «azúcares» son las ''guardas'', que utilizan valores booleanos para facilitar la implementación de funciones de una manera muy sencilla. Primero, vamos a implementar la función de valor absoluto para números reales, también llamada [[w:Función modular|función modular o módulo]]. Su definición matemática establece que, si un número es positivo, su módulo es el propio número; si es negativo, su módulo es su opuesto, es decir, cero menos ese número.
<math>\text{abs}(x) = |x| = \begin{cases} x, & \mbox{si } x \ge 0 \\ -x, & \mbox{si } x < 0. \end{cases} </math>
En esta función, la expresión utilizada para calcular <math>|x|</math> depende del propio valor de <math>x</math>. Si <math>x \ge 0</math> es verdadero, utilizamos la primera expresión; si es falso, utilizamos la segunda. Para expresar este proceso de decisión en Haskell, empleamos guardas. La función quedaría así:<ref group=nota>Esta función ya está disponible en las bibliotecas estándar de Haskell con el nombre <code>abs</code>. No es necesario volver a implementarla.</ref>
<syntaxhighlight lang="haskell">
absoluto x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
Es interesante observar que el código anterior se parece bastante a la definición matemática. Veámoslo por partes:
* Comenzamos con una definición normal de una función. Primero escribimos el nombre, <code>absoluto</code>, y después especificamos la cantidad de argumentos que acepta: <code>x</code>.
* En lugar de escribir el signo <code>=</code> y comenzar la definición, escribimos dos alternativas de comportamiento justo debajo.<ref group=nota>En realidad, podríamos escribirlo todo en una sola línea, como <code>f x | caso 1 | caso 2</code>, pero siempre es preferible dividir el código en varias líneas para facilitar la lectura.</ref> Estas alternativas son las que llamamos ''guardas''. Debemos recordar que la indentación (los espacios en blanco antes de <code>|</code>) no es opcional: sirve para indicar que las guardas pertenecen al ámbito de la definición de <code>absoluto</code>.
* Cada guarda comienza con una barra vertical, <code>|</code>. Después de ella, escribimos una expresión que dé como resultado un valor booleano, también llamada condición booleana o ''predicado''. A continuación, aparece el resto de la definición, que comienza con <code>=</code>. La definición indicada en una guarda solo se evaluará si su predicado resulta ser <code>True</code>.
* El caso de <code>otherwise</code> se evalúa cuando ninguna de las condiciones anteriores es verdadera. En este ejemplo, si <code>x</code> no es menor que cero, entonces necesariamente es mayor o igual que cero. Por tanto, el predicado de la última guarda podría ser <code>x >= 0</code>, pero lo habitual es utilizar <code>otherwise</code> para abarcar todos los casos que no se hayan contemplado en las guardas anteriores.
{{nota|No hay nada mágico detrás de <code>otherwise</code>. En realidad, se define simplemente como <code>otherwise {{=}} True</code>. Esto significa que, siempre que se evalúe <code>otherwise</code>, devolverá <code>True</code> y, por tanto, se ejecutará la definición indicada en su guarda.}}
Observa que escribimos <code>0 - x</code> en lugar de <code>-x</code>. Esto se debe a que <code>-</code> ''no es'' una función de un argumento que devuelva <code>0 - x</code>. En realidad, se trata de una abreviatura sintáctica. Aunque resulta muy útil, suele causar conflictos cuando se utiliza junto con la función <code>(-)</code>, que es el operador de resta. Haz una prueba en GHCi: calcula 3 menos -4 sin utilizar paréntesis. Para evitar este tipo de problemas, hemos decidido escribir explícitamente <code>0 - x</code>.
== Guardas y <code>where</code> ==
Es bastante habitual utilizar <code>where</code> dentro de una función con guardas. Por ejemplo, para determinar cuántas soluciones reales tiene una [[w:Ecuación cuadrática|ecuación de segundo grado]] de la forma <math>ax^2+bx+c=0</math>, debemos calcular su discriminante, <math>\Delta = b^2 - 4ac</math>. Si es mayor que cero, hay dos raíces reales; si es igual a cero, hay una; y si es menor que cero, no hay ninguna. Una función de Haskell llamada <code>numSolsReales</code>, que calcule esta cantidad, podría escribirse así:
<syntaxhighlight lang = "haskell">
numSolsReales a b c
| delta > 0 = 2
| delta == 0 = 1
| otherwise = 0
where
delta = b^2 - 4*a*c
</syntaxhighlight>
== Notas ==
<references group=nota/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
jwvr4pkbyk1nm3olqijhmhqtdk6bho0
436505
436500
2026-10-14T12:50:41Z
Luciérnaga de conocimiento
119502
436505
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
== Igualdad y otras comparaciones ==
En el capítulo anterior, usamos signos de igualdad para definir variables y funciones en Haskell, como se muestra en el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
Esto significa que, durante la evaluación del programa, todas las apariciones de <code>r</code> se sustituyen por <code>5</code> dentro del mismo ámbito. De manera similar, al evaluar
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
todas las apariciones de <code>f</code> seguidas de un número (el argumento de <code>f</code>) se sustituyen por ese valor más tres.
En Matemáticas, el signo de igualdad se usa de manera diferente. Consideremos el siguiente problema:
{{Haskell/Ejercicios|1=
Resuelve el siguiente problema: <math>x+3=5</math>.
}}
En este caso, el problema no consiste en representar <math>5</math> como si fuera <math>x+3</math>, o viceversa. En realidad, tenemos una ''proposición'' que afirma que un número <math>x</math>, al sumarle 3, da como resultado 5. Resolver la ecuación significa encontrar el valor de <math>x</math>, si existe alguno, que haga verdadera la proposición. En este sencillo ejemplo, una simple manipulación algebraica nos muestra que <math>x=2</math>, es decir, <math>2</math> es el número que satisface la proposición, ya que <math>2+3=5</math>.
Comparar valores para comprobar si son iguales resulta bastante útil en programación. De hecho, es algo muy elemental y necesario. En Haskell, estas pruebas se parecen bastante a una ecuación. Sin embargo, como el signo igual ya se utiliza para definir algo, Haskell emplea un signo de igualdad ''doble'', <code>==</code>, para realizar comparaciones. Veamos:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
Aquí, GHCi devuelve <code>True</code> (''verdadero'', en inglés) porque <math>2 + 3</math> es igual a <math>5</math>. ¿Y si la ecuación no fuera verdadera?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
El resultado es <code>False</code> (''falso'', en inglés). Ahora vamos a utilizar la función <code>f</code> que definimos al comienzo de este capítulo:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
Como era de esperar. Puesto que <code>f 2</code> se evalúa como <code>2 + 3</code>, cuyo resultado es <code>5</code>, lo lógico es que <code>5 == 5</code> devuelva <code>True</code>.
También podemos comparar dos valores numéricos para averiguar cuál es mayor. Haskell dispone de varios operadores para estas pruebas: <code><</code>, para ''menor que''; <code>></code>, para ''mayor que''; <code><=</code>, para ''menor o igual que''; y <code>>=</code>, para ''mayor o igual que''. Estas pruebas funcionan exactamente igual que <code>==</code>, que significa ''igual a''. Por ejemplo, podríamos utilizar <code><</code> junto con la función <code>area</code> del capítulo anterior para comprobar si un círculo de cierto radio tiene un área menor que otro valor.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Valores booleanos ==
¿Qué sucede cuando GHCi tiene que determinar si estas comparaciones son verdaderas o falsas? Consideremos un caso diferente. Si introducimos una expresión aritmética en GHCi, esta se ''evalúa'' y el resultado numérico aparece en pantalla:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
Si sustituimos la expresión aritmética por su valor final en una comparación, sucede algo parecido:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Mientras que el «4» devuelto en el primer caso representa el recuento de alguna cosa, «True» es un ''valor'' que representa la verdad de una determinada proposición. Estos valores se conocen como '''booleanos'''.<ref group=nota>Este término se eligió en homenaje al matemático británico [[w:George Boole|George Boole]].</ref> Naturalmente, solo hay dos valores posibles, que ya se nos han presentado: <code>True</code> y <code>False</code>.
== Introducción a los tipos de datos ==
<code>True</code> y <code>False</code> son valores reales, no una simple analogía. En Haskell, los valores booleanos tienen el mismo ''estatus'' que los valores numéricos, y podemos manipularlos de manera similar. Veamos un ejemplo sencillo:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
En efecto, <code>True</code> es igual a <code>True</code>, y <code>True</code> no es igual a <code>False</code>. Ahora bien, ¿es posible determinar si <code>2</code> es igual a <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
El compilador produce un error. En realidad, la pregunta original ni siquiera tiene sentido. No se puede comparar un número con algo que no es un número, ni un valor booleano con algo que no es booleano. Haskell incorpora esta noción en el propio lenguaje, y el mensaje de error anterior, aunque es largo y un poco intimidante, expresa precisamente eso: a la izquierda de <code>==</code> hay un número (<code>Num</code>), por lo que se esperaba también un número a la derecha. Sin embargo, un valor booleano (<code>Bool</code>) no es un número, de modo que la prueba de igualdad falla.
Queda claro, entonces, que los valores se agrupan en '''tipos''', que establecen los límites de lo que podemos o no hacer con ellos. <code>True</code> y <code>False</code> son valores del tipo <code>Bool</code>. El caso de <code>2</code> es algo más complicado, porque en informática existen varios tipos de números, al igual que en Matemáticas, aunque no sean equivalentes. Pero, en definitiva, sigue siendo un dato numérico (<code>Num</code>). En general, esta característica restrictiva resulta muy valiosa, porque podemos aprovecharla para controlar el comportamiento de nuestros programas y establecer reglas que impidan utilizarlos con tipos de datos que ''no tienen sentido''. De este modo, garantizamos el funcionamiento correcto de lo que desarrollamos. Volveremos a tratar los tipos más adelante, ya que constituyen una parte importante del lenguaje Haskell.
== Operadores infijos ==
Una prueba de igualdad, como <code>2 == 2</code>, también es una expresión, al igual que una operación aritmética, como <code>2 + 2</code>. Ambos casos se evalúan básicamente de la misma manera. Cuando escribimos <code>2 == 2</code> en una sesión de GHCi, este «responde» con <code>True</code>, porque simplemente ha evaluado la expresión. En realidad, el operador <code>==</code> es una función de dos argumentos (el de la izquierda y el de la derecha de la igualdad). Sin embargo, su uso es diferente: Haskell permite escribir las funciones de dos argumentos como ''operadores infijos'', es decir, situados ''entre'' sus dos argumentos. Cuando el nombre de una función está formado por caracteres no alfanuméricos (<code>==</code>, por ejemplo), utilizarla como operador infijo es la forma más habitual. Si queremos utilizarla de la manera convencional, es decir, como un ''operador prefijo'' (con el nombre de la función antes de los argumentos), debemos encerrarla entre paréntesis. Veamos:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
También es posible transformar un valor booleano en otro mediante la ''negación''. <code>not</code> es la función de negación: transforma <code>True</code> en <code>False</code>, y <code>False</code> en <code>True</code>.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell ya dispone del operador de desigualdad: <code>/=</code>, que significa ''no es igual a''. Sin embargo, podríamos definirlo fácilmente mediante <code>not</code> y <code>==</code>:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Observa que podemos utilizar la notación de operadores infijos incluso al definirlos. Además, un operador puede definirse a partir de cualquier símbolo [[w:ASCII|ASCII]].
=== Otras operaciones booleanas ===
Existen otras operaciones booleanas muy útiles y necesarias: ''o'' e ''y''.
La operación ''A o B'' da como resultado verdadero si ''A'', ''B'' o ambos son verdaderos. En Haskell se representa mediante el operador <code>(||)</code>:
{{Haskell/GHCi|1=
Prelude> True {{!!}} True
True
Prelude> True {{!!}} False
True
Prelude> False {{!!}} True
True
Prelude> False {{!!}} False
False
}}
La operación ''A y B'' da como resultado verdadero si ''A'' y ''B'' son verdaderos. En Haskell se representa mediante el operador <code>(&&)</code>:
{{Haskell/GHCi|1=
Prelude> True && True
True
Prelude> True && False
False
Prelude> False && True
False
Prelude> False && False
False
}}
== Guardas ==
Los programas escritos en Haskell suelen utilizar operadores booleanos mediante una sintaxis muy cómoda y abreviada. Cuando una misma lógica se expresa con una sintaxis diferente, hablamos de [[w:Azúcar sintáctico|''azúcar sintáctico'']]. Esto significa que el código resulta más «agradable al paladar humano». Conviene recordar este término, porque aparece con frecuencia en los materiales sobre Haskell.
Uno de estos «azúcares» son las ''guardas'', que utilizan valores booleanos para facilitar la implementación de funciones de una manera muy sencilla. Primero, vamos a implementar la función de valor absoluto para números reales, también llamada [[w:Función modular|función modular o módulo]]. Su definición matemática establece que, si un número es positivo, su módulo es el propio número; si es negativo, su módulo es su opuesto, es decir, cero menos ese número.
<math>\text{abs}(x) = |x| = \begin{cases} x, & \mbox{si } x \ge 0 \\ -x, & \mbox{si } x < 0. \end{cases} </math>
En esta función, la expresión utilizada para calcular <math>|x|</math> depende del propio valor de <math>x</math>. Si <math>x \ge 0</math> es verdadero, utilizamos la primera expresión; si es falso, utilizamos la segunda. Para expresar este proceso de decisión en Haskell, empleamos guardas. La función quedaría así:<ref group=nota>Esta función ya está disponible en las bibliotecas estándar de Haskell con el nombre <code>abs</code>. No es necesario volver a implementarla.</ref>
<syntaxhighlight lang="haskell">
absoluto x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
Es interesante observar que el código anterior se parece bastante a la definición matemática. Veámoslo por partes:
* Comenzamos con una definición normal de una función. Primero escribimos el nombre, <code>absoluto</code>, y después especificamos la cantidad de argumentos que acepta: <code>x</code>.
* En lugar de escribir el signo <code>=</code> y comenzar la definición, escribimos dos alternativas de comportamiento justo debajo.<ref group=nota>En realidad, podríamos escribirlo todo en una sola línea, como <code>f x | caso 1 | caso 2</code>, pero siempre es preferible dividir el código en varias líneas para facilitar la lectura.</ref> Estas alternativas son las que llamamos ''guardas''. Debemos recordar que la indentación (los espacios en blanco antes de <code>|</code>) no es opcional: sirve para indicar que las guardas pertenecen al ámbito de la definición de <code>absoluto</code>.
* Cada guarda comienza con una barra vertical, <code>|</code>. Después de ella, escribimos una expresión que dé como resultado un valor booleano, también llamada condición booleana o ''predicado''. A continuación, aparece el resto de la definición, que comienza con <code>=</code>. La definición indicada en una guarda solo se evaluará si su predicado resulta ser <code>True</code>.
* El caso de <code>otherwise</code> se evalúa cuando ninguna de las condiciones anteriores es verdadera. En este ejemplo, si <code>x</code> no es menor que cero, entonces necesariamente es mayor o igual que cero. Por tanto, el predicado de la última guarda podría ser <code>x >= 0</code>, pero lo habitual es utilizar <code>otherwise</code> para abarcar todos los casos que no se hayan contemplado en las guardas anteriores.
{{nota|No hay nada mágico detrás de <code>otherwise</code>. En realidad, se define simplemente como <code>otherwise {{=}} True</code>. Esto significa que, siempre que se evalúe <code>otherwise</code>, devolverá <code>True</code> y, por tanto, se ejecutará la definición indicada en su guarda.}}
Observa que escribimos <code>0 - x</code> en lugar de <code>-x</code>. Esto se debe a que <code>-</code> ''no es'' una función de un argumento que devuelva <code>0 - x</code>. En realidad, se trata de una abreviatura sintáctica. Aunque resulta muy útil, suele causar conflictos cuando se utiliza junto con la función <code>(-)</code>, que es el operador de resta. Haz una prueba en GHCi: calcula 3 menos -4 sin utilizar paréntesis. Para evitar este tipo de problemas, hemos decidido escribir explícitamente <code>0 - x</code>.
== Guardas y <code>where</code> ==
Es bastante habitual utilizar <code>where</code> dentro de una función con guardas. Por ejemplo, para determinar cuántas soluciones reales tiene una [[w:Ecuación cuadrática|ecuación de segundo grado]] de la forma <math>ax^2+bx+c=0</math>, debemos calcular su discriminante, <math>\Delta = b^2 - 4ac</math>. Si es mayor que cero, hay dos raíces reales; si es igual a cero, hay una; y si es menor que cero, no hay ninguna. Una función de Haskell llamada <code>numSolsReales</code>, que calcule esta cantidad, podría escribirse así:
<syntaxhighlight lang = "haskell">
numSolsReales a b c
| delta > 0 = 2
| delta == 0 = 1
| otherwise = 0
where
delta = b^2 - 4*a*c
</syntaxhighlight>
== Notas ==
<references group=nota/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
kx98pbpzziirqcedoeqfmyeef2gkuje
436506
436505
2026-10-14T12:54:46Z
Luciérnaga de conocimiento
119502
436506
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
== Igualdad y otras comparaciones ==
En el capítulo anterior, usamos signos de igualdad para definir variables y funciones en Haskell, como se muestra en el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
Esto significa que, durante la evaluación del programa, todas las apariciones de <code>r</code> se sustituyen por <code>5</code> dentro del mismo ámbito. De manera similar, al evaluar
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
todas las apariciones de <code>f</code> seguidas de un número (el argumento de <code>f</code>) se sustituyen por ese valor más tres.
En Matemáticas, el signo de igualdad se usa de manera diferente. Consideremos el siguiente problema:
{{Haskell/Ejercicios|1=
Resuelve el siguiente problema: <math>x+3=5</math>.
}}
En este caso, el problema no consiste en representar <math>5</math> como si fuera <math>x+3</math>, o viceversa. En realidad, tenemos una ''proposición'' que afirma que un número <math>x</math>, al sumarle 3, da como resultado 5. Resolver la ecuación significa encontrar el valor de <math>x</math>, si existe alguno, que haga verdadera la proposición. En este sencillo ejemplo, una simple manipulación algebraica nos muestra que <math>x=2</math>, es decir, <math>2</math> es el número que satisface la proposición, ya que <math>2+3=5</math>.
Comparar valores para comprobar si son iguales resulta bastante útil en programación. De hecho, es algo muy elemental y necesario. En Haskell, estas pruebas se parecen bastante a una ecuación. Sin embargo, como el signo igual ya se utiliza para definir algo, Haskell emplea un signo de igualdad ''doble'', <code>==</code>, para realizar comparaciones. Veamos:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
Aquí, GHCi devuelve <code>True</code> (''verdadero'', en inglés) porque <math>2 + 3</math> es igual a <math>5</math>. ¿Y si la ecuación no fuera verdadera?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
El resultado es <code>False</code> (''falso'', en inglés). Ahora vamos a utilizar la función <code>f</code> que definimos al comienzo de este capítulo:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
Como era de esperar. Puesto que <code>f 2</code> se evalúa como <code>2 + 3</code>, cuyo resultado es <code>5</code>, lo lógico es que <code>5 == 5</code> devuelva <code>True</code>.
También podemos comparar dos valores numéricos para averiguar cuál es mayor. Haskell dispone de varios operadores para estas pruebas: <code><</code>, para ''menor que''; <code>></code>, para ''mayor que''; <code><=</code>, para ''menor o igual que''; y <code>>=</code>, para ''mayor o igual que''. Estas pruebas funcionan exactamente igual que <code>==</code>, que significa ''igual a''. Por ejemplo, podríamos utilizar <code><</code> junto con la función <code>area</code> del capítulo anterior para comprobar si un círculo de cierto radio tiene un área menor que otro valor.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Valores booleanos ==
¿Qué sucede cuando GHCi tiene que determinar si estas comparaciones son verdaderas o falsas? Consideremos un caso diferente. Si introducimos una expresión aritmética en GHCi, esta se ''evalúa'' y el resultado numérico aparece en pantalla:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
Si sustituimos la expresión aritmética por su valor final en una comparación, sucede algo parecido:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Mientras que el «4» devuelto en el primer caso representa el recuento de alguna cosa, «True» es un ''valor'' que representa la verdad de una determinada proposición. Estos valores se conocen como '''booleanos'''.<ref group=nota>Este término se eligió en homenaje al matemático británico [[w:George Boole|George Boole]].</ref> Naturalmente, solo hay dos valores posibles, que ya se nos han presentado: <code>True</code> y <code>False</code>.
== Introducción a los tipos de datos ==
<code>True</code> y <code>False</code> son valores reales, no una simple analogía. En Haskell, los valores booleanos tienen el mismo ''estatus'' que los valores numéricos, y podemos manipularlos de manera similar. Veamos un ejemplo sencillo:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
En efecto, <code>True</code> es igual a <code>True</code>, y <code>True</code> no es igual a <code>False</code>. Ahora bien, ¿es posible determinar si <code>2</code> es igual a <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
El compilador produce un error. En realidad, la pregunta original ni siquiera tiene sentido. No se puede comparar un número con algo que no es un número, ni un valor booleano con algo que no es booleano. Haskell incorpora esta noción en el propio lenguaje, y el mensaje de error anterior, aunque es largo y un poco intimidante, expresa precisamente eso: a la izquierda de <code>==</code> hay un número (<code>Num</code>), por lo que se esperaba también un número a la derecha. Sin embargo, un valor booleano (<code>Bool</code>) no es un número, de modo que la prueba de igualdad falla.
Queda claro, entonces, que los valores se agrupan en '''tipos''', que establecen los límites de lo que podemos o no hacer con ellos. <code>True</code> y <code>False</code> son valores del tipo <code>Bool</code>. El caso de <code>2</code> es algo más complicado, porque en informática existen varios tipos de números, al igual que en Matemáticas, aunque no sean equivalentes. Pero, en definitiva, sigue siendo un dato numérico (<code>Num</code>). En general, esta característica restrictiva resulta muy valiosa, porque podemos aprovecharla para controlar el comportamiento de nuestros programas y establecer reglas que impidan utilizarlos con tipos de datos que ''no tienen sentido''. De este modo, garantizamos el funcionamiento correcto de lo que desarrollamos. Volveremos a tratar los tipos más adelante, ya que constituyen una parte importante del lenguaje Haskell.
== Operadores infijos ==
Una prueba de igualdad, como <code>2 == 2</code>, también es una expresión, al igual que una operación aritmética, como <code>2 + 2</code>. Ambos casos se evalúan básicamente de la misma manera. Cuando escribimos <code>2 == 2</code> en una sesión de GHCi, este «responde» con <code>True</code>, porque simplemente ha evaluado la expresión. En realidad, el operador <code>==</code> es una función de dos argumentos (el de la izquierda y el de la derecha de la igualdad). Sin embargo, su uso es diferente: Haskell permite escribir las funciones de dos argumentos como ''operadores infijos'', es decir, situados ''entre'' sus dos argumentos. Cuando el nombre de una función está formado por caracteres no alfanuméricos (<code>==</code>, por ejemplo), utilizarla como operador infijo es la forma más habitual. Si queremos utilizarla de la manera convencional, es decir, como un ''operador prefijo'' (con el nombre de la función antes de los argumentos), debemos encerrarla entre paréntesis. Veamos:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
También es posible transformar un valor booleano en otro mediante la ''negación''. <code>not</code> es la función de negación: transforma <code>True</code> en <code>False</code>, y <code>False</code> en <code>True</code>.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell ya dispone del operador de desigualdad: <code>/=</code>, que significa ''no es igual a''. Sin embargo, podríamos definirlo fácilmente mediante <code>not</code> y <code>==</code>:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Observa que podemos utilizar la notación de operadores infijos incluso al definirlos. Además, un operador puede definirse a partir de cualquier símbolo [[w:ASCII|ASCII]].
=== Otras operaciones booleanas ===
Existen otras operaciones booleanas muy útiles y necesarias: ''o'' e ''y''.
La operación ''A o B'' da como resultado verdadero si ''A'', ''B'' o ambos son verdaderos. En Haskell se representa mediante el operador <code>(||)</code>:
{{Haskell/GHCi|1=
Prelude> True || True
True
Prelude> True || False
True
Prelude> False || True
True
Prelude> False || False
False
}}
La operación ''A y B'' da como resultado verdadero si ''A'' y ''B'' son verdaderos. En Haskell se representa mediante el operador <code>(&&)</code>:
{{Haskell/GHCi|1=
Prelude> True && True
True
Prelude> True && False
False
Prelude> False && True
False
Prelude> False && False
False
}}
== Guardas ==
Los programas escritos en Haskell suelen utilizar operadores booleanos mediante una sintaxis muy cómoda y abreviada. Cuando una misma lógica se expresa con una sintaxis diferente, hablamos de [[w:Azúcar sintáctico|''azúcar sintáctico'']]. Esto significa que el código resulta más «agradable al paladar humano». Conviene recordar este término, porque aparece con frecuencia en los materiales sobre Haskell.
Uno de estos «azúcares» son las ''guardas'', que utilizan valores booleanos para facilitar la implementación de funciones de una manera muy sencilla. Primero, vamos a implementar la función de valor absoluto para números reales, también llamada [[w:Función modular|función modular o módulo]]. Su definición matemática establece que, si un número es positivo, su módulo es el propio número; si es negativo, su módulo es su opuesto, es decir, cero menos ese número.
<math>\text{abs}(x) = |x| = \begin{cases} x, & \mbox{si } x \ge 0 \\ -x, & \mbox{si } x < 0. \end{cases} </math>
En esta función, la expresión utilizada para calcular <math>|x|</math> depende del propio valor de <math>x</math>. Si <math>x \ge 0</math> es verdadero, utilizamos la primera expresión; si es falso, utilizamos la segunda. Para expresar este proceso de decisión en Haskell, empleamos guardas. La función quedaría así:<ref group=nota>Esta función ya está disponible en las bibliotecas estándar de Haskell con el nombre <code>abs</code>. No es necesario volver a implementarla.</ref>
<syntaxhighlight lang="haskell">
absoluto x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
Es interesante observar que el código anterior se parece bastante a la definición matemática. Veámoslo por partes:
* Comenzamos con una definición normal de una función. Primero escribimos el nombre, <code>absoluto</code>, y después especificamos la cantidad de argumentos que acepta: <code>x</code>.
* En lugar de escribir el signo <code>=</code> y comenzar la definición, escribimos dos alternativas de comportamiento justo debajo.<ref group=nota>En realidad, podríamos escribirlo todo en una sola línea, como <code>f x | caso 1 | caso 2</code>, pero siempre es preferible dividir el código en varias líneas para facilitar la lectura.</ref> Estas alternativas son las que llamamos ''guardas''. Debemos recordar que la indentación (los espacios en blanco antes de <code>|</code>) no es opcional: sirve para indicar que las guardas pertenecen al ámbito de la definición de <code>absoluto</code>.
* Cada guarda comienza con una barra vertical, <code>|</code>. Después de ella, escribimos una expresión que dé como resultado un valor booleano, también llamada condición booleana o ''predicado''. A continuación, aparece el resto de la definición, que comienza con <code>=</code>. La definición indicada en una guarda solo se evaluará si su predicado resulta ser <code>True</code>.
* El caso de <code>otherwise</code> se evalúa cuando ninguna de las condiciones anteriores es verdadera. En este ejemplo, si <code>x</code> no es menor que cero, entonces necesariamente es mayor o igual que cero. Por tanto, el predicado de la última guarda podría ser <code>x >= 0</code>, pero lo habitual es utilizar <code>otherwise</code> para abarcar todos los casos que no se hayan contemplado en las guardas anteriores.
{{nota|No hay nada mágico detrás de <code>otherwise</code>. En realidad, se define simplemente como <code>otherwise {{=}} True</code>. Esto significa que, siempre que se evalúe <code>otherwise</code>, devolverá <code>True</code> y, por tanto, se ejecutará la definición indicada en su guarda.}}
Observa que escribimos <code>0 - x</code> en lugar de <code>-x</code>. Esto se debe a que <code>-</code> ''no es'' una función de un argumento que devuelva <code>0 - x</code>. En realidad, se trata de una abreviatura sintáctica. Aunque resulta muy útil, suele causar conflictos cuando se utiliza junto con la función <code>(-)</code>, que es el operador de resta. Haz una prueba en GHCi: calcula 3 menos -4 sin utilizar paréntesis. Para evitar este tipo de problemas, hemos decidido escribir explícitamente <code>0 - x</code>.
== Guardas y <code>where</code> ==
Es bastante habitual utilizar <code>where</code> dentro de una función con guardas. Por ejemplo, para determinar cuántas soluciones reales tiene una [[w:Ecuación cuadrática|ecuación de segundo grado]] de la forma <math>ax^2+bx+c=0</math>, debemos calcular su discriminante, <math>\Delta = b^2 - 4ac</math>. Si es mayor que cero, hay dos raíces reales; si es igual a cero, hay una; y si es menor que cero, no hay ninguna. Una función de Haskell llamada <code>numSolsReales</code>, que calcule esta cantidad, podría escribirse así:
<syntaxhighlight lang = "haskell">
numSolsReales a b c
| delta > 0 = 2
| delta == 0 = 1
| otherwise = 0
where
delta = b^2 - 4*a*c
</syntaxhighlight>
== Notas ==
<references group=nota/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
imtr1j5hsoxsd5vcocso7jedxactexf
436507
436506
2026-10-14T12:56:28Z
Luciérnaga de conocimiento
119502
/* Otras operaciones booleanas */
436507
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
== Igualdad y otras comparaciones ==
En el capítulo anterior, usamos signos de igualdad para definir variables y funciones en Haskell, como se muestra en el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
Esto significa que, durante la evaluación del programa, todas las apariciones de <code>r</code> se sustituyen por <code>5</code> dentro del mismo ámbito. De manera similar, al evaluar
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
todas las apariciones de <code>f</code> seguidas de un número (el argumento de <code>f</code>) se sustituyen por ese valor más tres.
En Matemáticas, el signo de igualdad se usa de manera diferente. Consideremos el siguiente problema:
{{Haskell/Ejercicios|1=
Resuelve el siguiente problema: <math>x+3=5</math>.
}}
En este caso, el problema no consiste en representar <math>5</math> como si fuera <math>x+3</math>, o viceversa. En realidad, tenemos una ''proposición'' que afirma que un número <math>x</math>, al sumarle 3, da como resultado 5. Resolver la ecuación significa encontrar el valor de <math>x</math>, si existe alguno, que haga verdadera la proposición. En este sencillo ejemplo, una simple manipulación algebraica nos muestra que <math>x=2</math>, es decir, <math>2</math> es el número que satisface la proposición, ya que <math>2+3=5</math>.
Comparar valores para comprobar si son iguales resulta bastante útil en programación. De hecho, es algo muy elemental y necesario. En Haskell, estas pruebas se parecen bastante a una ecuación. Sin embargo, como el signo igual ya se utiliza para definir algo, Haskell emplea un signo de igualdad ''doble'', <code>==</code>, para realizar comparaciones. Veamos:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
Aquí, GHCi devuelve <code>True</code> (''verdadero'', en inglés) porque <math>2 + 3</math> es igual a <math>5</math>. ¿Y si la ecuación no fuera verdadera?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
El resultado es <code>False</code> (''falso'', en inglés). Ahora vamos a utilizar la función <code>f</code> que definimos al comienzo de este capítulo:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
Como era de esperar. Puesto que <code>f 2</code> se evalúa como <code>2 + 3</code>, cuyo resultado es <code>5</code>, lo lógico es que <code>5 == 5</code> devuelva <code>True</code>.
También podemos comparar dos valores numéricos para averiguar cuál es mayor. Haskell dispone de varios operadores para estas pruebas: <code><</code>, para ''menor que''; <code>></code>, para ''mayor que''; <code><=</code>, para ''menor o igual que''; y <code>>=</code>, para ''mayor o igual que''. Estas pruebas funcionan exactamente igual que <code>==</code>, que significa ''igual a''. Por ejemplo, podríamos utilizar <code><</code> junto con la función <code>area</code> del capítulo anterior para comprobar si un círculo de cierto radio tiene un área menor que otro valor.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Valores booleanos ==
¿Qué sucede cuando GHCi tiene que determinar si estas comparaciones son verdaderas o falsas? Consideremos un caso diferente. Si introducimos una expresión aritmética en GHCi, esta se ''evalúa'' y el resultado numérico aparece en pantalla:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
Si sustituimos la expresión aritmética por su valor final en una comparación, sucede algo parecido:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Mientras que el «4» devuelto en el primer caso representa el recuento de alguna cosa, «True» es un ''valor'' que representa la verdad de una determinada proposición. Estos valores se conocen como '''booleanos'''.<ref group=nota>Este término se eligió en homenaje al matemático británico [[w:George Boole|George Boole]].</ref> Naturalmente, solo hay dos valores posibles, que ya se nos han presentado: <code>True</code> y <code>False</code>.
== Introducción a los tipos de datos ==
<code>True</code> y <code>False</code> son valores reales, no una simple analogía. En Haskell, los valores booleanos tienen el mismo ''estatus'' que los valores numéricos, y podemos manipularlos de manera similar. Veamos un ejemplo sencillo:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
En efecto, <code>True</code> es igual a <code>True</code>, y <code>True</code> no es igual a <code>False</code>. Ahora bien, ¿es posible determinar si <code>2</code> es igual a <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
El compilador produce un error. En realidad, la pregunta original ni siquiera tiene sentido. No se puede comparar un número con algo que no es un número, ni un valor booleano con algo que no es booleano. Haskell incorpora esta noción en el propio lenguaje, y el mensaje de error anterior, aunque es largo y un poco intimidante, expresa precisamente eso: a la izquierda de <code>==</code> hay un número (<code>Num</code>), por lo que se esperaba también un número a la derecha. Sin embargo, un valor booleano (<code>Bool</code>) no es un número, de modo que la prueba de igualdad falla.
Queda claro, entonces, que los valores se agrupan en '''tipos''', que establecen los límites de lo que podemos o no hacer con ellos. <code>True</code> y <code>False</code> son valores del tipo <code>Bool</code>. El caso de <code>2</code> es algo más complicado, porque en informática existen varios tipos de números, al igual que en Matemáticas, aunque no sean equivalentes. Pero, en definitiva, sigue siendo un dato numérico (<code>Num</code>). En general, esta característica restrictiva resulta muy valiosa, porque podemos aprovecharla para controlar el comportamiento de nuestros programas y establecer reglas que impidan utilizarlos con tipos de datos que ''no tienen sentido''. De este modo, garantizamos el funcionamiento correcto de lo que desarrollamos. Volveremos a tratar los tipos más adelante, ya que constituyen una parte importante del lenguaje Haskell.
== Operadores infijos ==
Una prueba de igualdad, como <code>2 == 2</code>, también es una expresión, al igual que una operación aritmética, como <code>2 + 2</code>. Ambos casos se evalúan básicamente de la misma manera. Cuando escribimos <code>2 == 2</code> en una sesión de GHCi, este «responde» con <code>True</code>, porque simplemente ha evaluado la expresión. En realidad, el operador <code>==</code> es una función de dos argumentos (el de la izquierda y el de la derecha de la igualdad). Sin embargo, su uso es diferente: Haskell permite escribir las funciones de dos argumentos como ''operadores infijos'', es decir, situados ''entre'' sus dos argumentos. Cuando el nombre de una función está formado por caracteres no alfanuméricos (<code>==</code>, por ejemplo), utilizarla como operador infijo es la forma más habitual. Si queremos utilizarla de la manera convencional, es decir, como un ''operador prefijo'' (con el nombre de la función antes de los argumentos), debemos encerrarla entre paréntesis. Veamos:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
También es posible transformar un valor booleano en otro mediante la ''negación''. <code>not</code> es la función de negación: transforma <code>True</code> en <code>False</code>, y <code>False</code> en <code>True</code>.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell ya dispone del operador de desigualdad: <code>/=</code>, que significa ''no es igual a''. Sin embargo, podríamos definirlo fácilmente mediante <code>not</code> y <code>==</code>:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Observa que podemos utilizar la notación de operadores infijos incluso al definirlos. Además, un operador puede definirse a partir de cualquier símbolo [[w:ASCII|ASCII]].
=== Otras operaciones booleanas ===
Existen otras operaciones booleanas muy útiles y necesarias: ''o'' e ''y''.
La operación ''A o B'' da como resultado verdadero si ''A'', ''B'' o ambos son verdaderos. En Haskell se representa mediante el operador <code>(||)</code>:
{{Haskell/GHCi|1=
Prelude> True <nowiki>||</nowiki> True
True
Prelude> True <nowiki>||</nowiki> False
True
Prelude> False <nowiki>||</nowiki> True
True
Prelude> False <nowiki>||</nowiki> False
False
}}
La operación ''A y B'' da como resultado verdadero si ''A'' y ''B'' son verdaderos. En Haskell se representa mediante el operador <code>(&&)</code>:
{{Haskell/GHCi|1=
Prelude> True && True
True
Prelude> True && False
False
Prelude> False && True
False
Prelude> False && False
False
}}
== Guardas ==
Los programas escritos en Haskell suelen utilizar operadores booleanos mediante una sintaxis muy cómoda y abreviada. Cuando una misma lógica se expresa con una sintaxis diferente, hablamos de [[w:Azúcar sintáctico|''azúcar sintáctico'']]. Esto significa que el código resulta más «agradable al paladar humano». Conviene recordar este término, porque aparece con frecuencia en los materiales sobre Haskell.
Uno de estos «azúcares» son las ''guardas'', que utilizan valores booleanos para facilitar la implementación de funciones de una manera muy sencilla. Primero, vamos a implementar la función de valor absoluto para números reales, también llamada [[w:Función modular|función modular o módulo]]. Su definición matemática establece que, si un número es positivo, su módulo es el propio número; si es negativo, su módulo es su opuesto, es decir, cero menos ese número.
<math>\text{abs}(x) = |x| = \begin{cases} x, & \mbox{si } x \ge 0 \\ -x, & \mbox{si } x < 0. \end{cases} </math>
En esta función, la expresión utilizada para calcular <math>|x|</math> depende del propio valor de <math>x</math>. Si <math>x \ge 0</math> es verdadero, utilizamos la primera expresión; si es falso, utilizamos la segunda. Para expresar este proceso de decisión en Haskell, empleamos guardas. La función quedaría así:<ref group=nota>Esta función ya está disponible en las bibliotecas estándar de Haskell con el nombre <code>abs</code>. No es necesario volver a implementarla.</ref>
<syntaxhighlight lang="haskell">
absoluto x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
Es interesante observar que el código anterior se parece bastante a la definición matemática. Veámoslo por partes:
* Comenzamos con una definición normal de una función. Primero escribimos el nombre, <code>absoluto</code>, y después especificamos la cantidad de argumentos que acepta: <code>x</code>.
* En lugar de escribir el signo <code>=</code> y comenzar la definición, escribimos dos alternativas de comportamiento justo debajo.<ref group=nota>En realidad, podríamos escribirlo todo en una sola línea, como <code>f x | caso 1 | caso 2</code>, pero siempre es preferible dividir el código en varias líneas para facilitar la lectura.</ref> Estas alternativas son las que llamamos ''guardas''. Debemos recordar que la indentación (los espacios en blanco antes de <code>|</code>) no es opcional: sirve para indicar que las guardas pertenecen al ámbito de la definición de <code>absoluto</code>.
* Cada guarda comienza con una barra vertical, <code>|</code>. Después de ella, escribimos una expresión que dé como resultado un valor booleano, también llamada condición booleana o ''predicado''. A continuación, aparece el resto de la definición, que comienza con <code>=</code>. La definición indicada en una guarda solo se evaluará si su predicado resulta ser <code>True</code>.
* El caso de <code>otherwise</code> se evalúa cuando ninguna de las condiciones anteriores es verdadera. En este ejemplo, si <code>x</code> no es menor que cero, entonces necesariamente es mayor o igual que cero. Por tanto, el predicado de la última guarda podría ser <code>x >= 0</code>, pero lo habitual es utilizar <code>otherwise</code> para abarcar todos los casos que no se hayan contemplado en las guardas anteriores.
{{nota|No hay nada mágico detrás de <code>otherwise</code>. En realidad, se define simplemente como <code>otherwise {{=}} True</code>. Esto significa que, siempre que se evalúe <code>otherwise</code>, devolverá <code>True</code> y, por tanto, se ejecutará la definición indicada en su guarda.}}
Observa que escribimos <code>0 - x</code> en lugar de <code>-x</code>. Esto se debe a que <code>-</code> ''no es'' una función de un argumento que devuelva <code>0 - x</code>. En realidad, se trata de una abreviatura sintáctica. Aunque resulta muy útil, suele causar conflictos cuando se utiliza junto con la función <code>(-)</code>, que es el operador de resta. Haz una prueba en GHCi: calcula 3 menos -4 sin utilizar paréntesis. Para evitar este tipo de problemas, hemos decidido escribir explícitamente <code>0 - x</code>.
== Guardas y <code>where</code> ==
Es bastante habitual utilizar <code>where</code> dentro de una función con guardas. Por ejemplo, para determinar cuántas soluciones reales tiene una [[w:Ecuación cuadrática|ecuación de segundo grado]] de la forma <math>ax^2+bx+c=0</math>, debemos calcular su discriminante, <math>\Delta = b^2 - 4ac</math>. Si es mayor que cero, hay dos raíces reales; si es igual a cero, hay una; y si es menor que cero, no hay ninguna. Una función de Haskell llamada <code>numSolsReales</code>, que calcule esta cantidad, podría escribirse así:
<syntaxhighlight lang = "haskell">
numSolsReales a b c
| delta > 0 = 2
| delta == 0 = 1
| otherwise = 0
where
delta = b^2 - 4*a*c
</syntaxhighlight>
== Notas ==
<references group=nota/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
1wszf1pgsnzarnycy6g3t7dllz8y6oq
436516
436507
2026-10-14T13:08:01Z
Luciérnaga de conocimiento
119502
436516
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Valores de verdad|título=Principios básicos de Haskell|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
== Igualdad y otras comparaciones ==
En el capítulo anterior, usamos signos de igualdad para definir variables y funciones en Haskell, como se muestra en el siguiente código:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
Esto significa que, durante la evaluación del programa, todas las apariciones de <code>r</code> se sustituyen por <code>5</code> dentro del mismo ámbito. De manera similar, al evaluar
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
todas las apariciones de <code>f</code> seguidas de un número (el argumento de <code>f</code>) se sustituyen por ese valor más tres.
En Matemáticas, el signo de igualdad se usa de manera diferente. Consideremos el siguiente problema:
{{Haskell/Ejercicios|1=
Resuelve el siguiente problema: <math>x+3=5</math>.
}}
En este caso, el problema no consiste en representar <math>5</math> como si fuera <math>x+3</math>, o viceversa. En realidad, tenemos una ''proposición'' que afirma que un número <math>x</math>, al sumarle 3, da como resultado 5. Resolver la ecuación significa encontrar el valor de <math>x</math>, si existe alguno, que haga verdadera la proposición. En este sencillo ejemplo, una simple manipulación algebraica nos muestra que <math>x=2</math>, es decir, <math>2</math> es el número que satisface la proposición, ya que <math>2+3=5</math>.
Comparar valores para comprobar si son iguales resulta bastante útil en programación. De hecho, es algo muy elemental y necesario. En Haskell, estas pruebas se parecen bastante a una ecuación. Sin embargo, como el signo igual ya se utiliza para definir algo, Haskell emplea un signo de igualdad ''doble'', <code>==</code>, para realizar comparaciones. Veamos:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
Aquí, GHCi devuelve <code>True</code> (''verdadero'', en inglés) porque <math>2 + 3</math> es igual a <math>5</math>. ¿Y si la ecuación no fuera verdadera?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
El resultado es <code>False</code> (''falso'', en inglés). Ahora vamos a utilizar la función <code>f</code> que definimos al comienzo de este capítulo:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
Como era de esperar. Puesto que <code>f 2</code> se evalúa como <code>2 + 3</code>, cuyo resultado es <code>5</code>, lo lógico es que <code>5 == 5</code> devuelva <code>True</code>.
También podemos comparar dos valores numéricos para averiguar cuál es mayor. Haskell dispone de varios operadores para estas pruebas: <code><</code>, para ''menor que''; <code>></code>, para ''mayor que''; <code><=</code>, para ''menor o igual que''; y <code>>=</code>, para ''mayor o igual que''. Estas pruebas funcionan exactamente igual que <code>==</code>, que significa ''igual a''. Por ejemplo, podríamos utilizar <code><</code> junto con la función <code>area</code> del capítulo anterior para comprobar si un círculo de cierto radio tiene un área menor que otro valor.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Valores booleanos ==
¿Qué sucede cuando GHCi tiene que determinar si estas comparaciones son verdaderas o falsas? Consideremos un caso diferente. Si introducimos una expresión aritmética en GHCi, esta se ''evalúa'' y el resultado numérico aparece en pantalla:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
Si sustituimos la expresión aritmética por su valor final en una comparación, sucede algo parecido:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Mientras que el «4» devuelto en el primer caso representa el recuento de alguna cosa, «True» es un ''valor'' que representa la verdad de una determinada proposición. Estos valores se conocen como '''booleanos'''.<ref group=nota>Este término se eligió en homenaje al matemático británico [[w:George Boole|George Boole]].</ref> Naturalmente, solo hay dos valores posibles, que ya se nos han presentado: <code>True</code> y <code>False</code>.
== Introducción a los tipos de datos ==
<code>True</code> y <code>False</code> son valores reales, no una simple analogía. En Haskell, los valores booleanos tienen el mismo ''estatus'' que los valores numéricos, y podemos manipularlos de manera similar. Veamos un ejemplo sencillo:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
En efecto, <code>True</code> es igual a <code>True</code>, y <code>True</code> no es igual a <code>False</code>. Ahora bien, ¿es posible determinar si <code>2</code> es igual a <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
El compilador produce un error. En realidad, la pregunta original ni siquiera tiene sentido. No se puede comparar un número con algo que no es un número, ni un valor booleano con algo que no es booleano. Haskell incorpora esta noción en el propio lenguaje, y el mensaje de error anterior, aunque es largo y un poco intimidante, expresa precisamente eso: a la izquierda de <code>==</code> hay un número (<code>Num</code>), por lo que se esperaba también un número a la derecha. Sin embargo, un valor booleano (<code>Bool</code>) no es un número, de modo que la prueba de igualdad falla.
Queda claro, entonces, que los valores se agrupan en '''tipos''', que establecen los límites de lo que podemos o no hacer con ellos. <code>True</code> y <code>False</code> son valores del tipo <code>Bool</code>. El caso de <code>2</code> es algo más complicado, porque en informática existen varios tipos de números, al igual que en Matemáticas, aunque no sean equivalentes. Pero, en definitiva, sigue siendo un dato numérico (<code>Num</code>). En general, esta característica restrictiva resulta muy valiosa, porque podemos aprovecharla para controlar el comportamiento de nuestros programas y establecer reglas que impidan utilizarlos con tipos de datos que ''no tienen sentido''. De este modo, garantizamos el funcionamiento correcto de lo que desarrollamos. Volveremos a tratar los tipos más adelante, ya que constituyen una parte importante del lenguaje Haskell.
== Operadores infijos ==
Una prueba de igualdad, como <code>2 == 2</code>, también es una expresión, al igual que una operación aritmética, como <code>2 + 2</code>. Ambos casos se evalúan básicamente de la misma manera. Cuando escribimos <code>2 == 2</code> en una sesión de GHCi, este «responde» con <code>True</code>, porque simplemente ha evaluado la expresión. En realidad, el operador <code>==</code> es una función de dos argumentos (el de la izquierda y el de la derecha de la igualdad). Sin embargo, su uso es diferente: Haskell permite escribir las funciones de dos argumentos como ''operadores infijos'', es decir, situados ''entre'' sus dos argumentos. Cuando el nombre de una función está formado por caracteres no alfanuméricos (<code>==</code>, por ejemplo), utilizarla como operador infijo es la forma más habitual. Si queremos utilizarla de la manera convencional, es decir, como un ''operador prefijo'' (con el nombre de la función antes de los argumentos), debemos encerrarla entre paréntesis. Veamos:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
También es posible transformar un valor booleano en otro mediante la ''negación''. <code>not</code> es la función de negación: transforma <code>True</code> en <code>False</code>, y <code>False</code> en <code>True</code>.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell ya dispone del operador de desigualdad: <code>/=</code>, que significa ''no es igual a''. Sin embargo, podríamos definirlo fácilmente mediante <code>not</code> y <code>==</code>:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Observa que podemos utilizar la notación de operadores infijos incluso al definirlos. Además, un operador puede definirse a partir de cualquier símbolo [[w:ASCII|ASCII]].
=== Otras operaciones booleanas ===
Existen otras operaciones booleanas muy útiles y necesarias: ''o'' e ''y''.
La operación ''A o B'' da como resultado verdadero si ''A'', ''B'' o ambos son verdaderos. En Haskell se representa mediante el operador <code>(||)</code>:
{{Haskell/GHCi|1=
Prelude> True <nowiki>||</nowiki> True
True
Prelude> True <nowiki>||</nowiki> False
True
Prelude> False <nowiki>||</nowiki> True
True
Prelude> False <nowiki>||</nowiki> False
False
}}
La operación ''A y B'' da como resultado verdadero si ''A'' y ''B'' son verdaderos. En Haskell se representa mediante el operador <code>(&&)</code>:
{{Haskell/GHCi|1=
Prelude> True && True
True
Prelude> True && False
False
Prelude> False && True
False
Prelude> False && False
False
}}
== Guardas ==
Los programas escritos en Haskell suelen utilizar operadores booleanos mediante una sintaxis muy cómoda y abreviada. Cuando una misma lógica se expresa con una sintaxis diferente, hablamos de [[w:Azúcar sintáctico|''azúcar sintáctico'']]. Esto significa que el código resulta más «agradable al paladar humano». Conviene recordar este término, porque aparece con frecuencia en los materiales sobre Haskell.
Uno de estos «azúcares» son las ''guardas'', que utilizan valores booleanos para facilitar la implementación de funciones de una manera muy sencilla. Primero, vamos a implementar la función de valor absoluto para números reales, también llamada [[w:Función modular|función modular o módulo]]. Su definición matemática establece que, si un número es positivo, su módulo es el propio número; si es negativo, su módulo es su opuesto, es decir, cero menos ese número.
<math>\text{abs}(x) = |x| = \begin{cases} x, & \mbox{si } x \ge 0 \\ -x, & \mbox{si } x < 0. \end{cases} </math>
En esta función, la expresión utilizada para calcular <math>|x|</math> depende del propio valor de <math>x</math>. Si <math>x \ge 0</math> es verdadero, utilizamos la primera expresión; si es falso, utilizamos la segunda. Para expresar este proceso de decisión en Haskell, empleamos guardas. La función quedaría así:<ref group=nota>Esta función ya está disponible en las bibliotecas estándar de Haskell con el nombre <code>abs</code>. No es necesario volver a implementarla.</ref>
<syntaxhighlight lang="haskell">
absoluto x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
Es interesante observar que el código anterior se parece bastante a la definición matemática. Veámoslo por partes:
* Comenzamos con una definición normal de una función. Primero escribimos el nombre, <code>absoluto</code>, y después especificamos la cantidad de argumentos que acepta: <code>x</code>.
* En lugar de escribir el signo <code>=</code> y comenzar la definición, escribimos dos alternativas de comportamiento justo debajo.<ref group=nota>En realidad, podríamos escribirlo todo en una sola línea, como <code>f x | caso 1 | caso 2</code>, pero siempre es preferible dividir el código en varias líneas para facilitar la lectura.</ref> Estas alternativas son las que llamamos ''guardas''. Debemos recordar que la indentación (los espacios en blanco antes de <code>|</code>) no es opcional: sirve para indicar que las guardas pertenecen al ámbito de la definición de <code>absoluto</code>.
* Cada guarda comienza con una barra vertical, <code>|</code>. Después de ella, escribimos una expresión que dé como resultado un valor booleano, también llamada condición booleana o ''predicado''. A continuación, aparece el resto de la definición, que comienza con <code>=</code>. La definición indicada en una guarda solo se evaluará si su predicado resulta ser <code>True</code>.
* El caso de <code>otherwise</code> se evalúa cuando ninguna de las condiciones anteriores es verdadera. En este ejemplo, si <code>x</code> no es menor que cero, entonces necesariamente es mayor o igual que cero. Por tanto, el predicado de la última guarda podría ser <code>x >= 0</code>, pero lo habitual es utilizar <code>otherwise</code> para abarcar todos los casos que no se hayan contemplado en las guardas anteriores.
{{nota|No hay nada mágico detrás de <code>otherwise</code>. En realidad, se define simplemente como <code>otherwise {{=}} True</code>. Esto significa que, siempre que se evalúe <code>otherwise</code>, devolverá <code>True</code> y, por tanto, se ejecutará la definición indicada en su guarda.}}
Observa que escribimos <code>0 - x</code> en lugar de <code>-x</code>. Esto se debe a que <code>-</code> ''no es'' una función de un argumento que devuelva <code>0 - x</code>. En realidad, se trata de una abreviatura sintáctica. Aunque resulta muy útil, suele causar conflictos cuando se utiliza junto con la función <code>(-)</code>, que es el operador de resta. Haz una prueba en GHCi: calcula 3 menos -4 sin utilizar paréntesis. Para evitar este tipo de problemas, hemos decidido escribir explícitamente <code>0 - x</code>.
== Guardas y <code>where</code> ==
Es bastante habitual utilizar <code>where</code> dentro de una función con guardas. Por ejemplo, para determinar cuántas soluciones reales tiene una [[w:Ecuación cuadrática|ecuación de segundo grado]] de la forma <math>ax^2+bx+c=0</math>, debemos calcular su discriminante, <math>\Delta = b^2 - 4ac</math>. Si es mayor que cero, hay dos raíces reales; si es igual a cero, hay una; y si es menor que cero, no hay ninguna. Una función de Haskell llamada <code>numSolsReales</code>, que calcule esta cantidad, podría escribirse así:
<syntaxhighlight lang = "haskell">
numSolsReales a b c
| delta > 0 = 2
| delta == 0 = 1
| otherwise = 0
where
delta = b^2 - 4*a*c
</syntaxhighlight>
== Notas ==
<references group=nota/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
b8qx72w8xjtnl8vuleree508i6a0xhk
Haskell/Tipos básicos
0
65086
436494
436482
2026-10-14T12:25:46Z
Luciérnaga de conocimiento
119502
436494
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Variables y funciones}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
7b3usr2171k5u15x6tir7hsq1u0gtac
436495
436494
2026-10-14T12:26:17Z
Luciérnaga de conocimiento
119502
436495
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Tipos básicos}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
j20onu40zcqqa0ep71rawax5w4tb24r
436496
436495
2026-10-14T12:26:35Z
Luciérnaga de conocimiento
119502
436496
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Variables y funciones}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
7b3usr2171k5u15x6tir7hsq1u0gtac
436501
436496
2026-10-14T12:37:49Z
Luciérnaga de conocimiento
119502
436501
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Tipo básicos}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
2mvzopj2d6qi2wrddy0urd6zmjb6n5c
436502
436501
2026-10-14T12:38:10Z
Luciérnaga de conocimiento
119502
436502
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Tipos básicos}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
j20onu40zcqqa0ep71rawax5w4tb24r
436517
436502
2026-10-14T13:08:23Z
Luciérnaga de conocimiento
119502
436517
wikitext
text/x-wiki
{{+ÍndiceSección|libro=Haskell|sección=Tipos básicos|título=Principios básicos de Haskell|navegación=Capítulo de Haskell/Principios básicos de Haskell}}
En programación, los '''tipos''' se utilizan para agrupar valores similares, con características comunes, dentro de una determinada categoría. En Haskell, su sistema de tipos es una herramienta poderosa que permite evitar muchos errores triviales en un programa.
== Introducción ==
Cuando se crea un programa, generalmente hay que trabajar con distintas entidades. Por ejemplo, consideremos la operación <math>2 + 3</math>. ¿Qué son 2 y 3? Números. ¿Y el signo más que aparece entre ellos? No es un número, sino un símbolo que representa la operación de suma que queremos realizar entre 2 y 3.
Ahora imaginemos un programa que nos pide nuestro nombre y nos saluda con un mensaje que dice «Hola». Ni nuestro nombre ni el mensaje son números, sino palabras. Por lo tanto, son texto. En programación, cuando nos referimos a texto, generalmente hablamos de ''String'', que significa «hilo» o «cadena» en inglés. Es una forma abreviada de decir «cadena de caracteres».
{{Nota al margen|En Haskell, existe una regla según la cual el nombre de cualquier tipo debe comenzar con una letra mayúscula. A partir de aquí, seguiremos siempre esta regla.}}
Una base de datos es un buen ejemplo para ilustrar los distintos tipos de datos que existen. Imaginemos que tenemos una tabla de contactos, como una agenda. Su contenido podría ser el siguiente:
{|class="wikitable"
| Primer nombre
| Apellido
| Dirección postal
| Número de teléfono
|-
| José
| Martínez
| Calle de Embajadores, 77, Lavapiés, Madrid, España.
| 184344
|-
| Juan
| Rodríguez
| Carrer de la Marina, 1025, El Poblenou, Barcelona, España.
| 724931
|}
Los campos de cada registro contienen valores diferentes. <tt>José</tt> es un valor, mientras que <tt>Calle de Embajadores, 77, Lavapiés, Madrid, España</tt> y <tt>184344</tt> son otros dos. En cuanto a sus tipos, «Primer nombre» y «Apellido» contienen texto, por lo que sus valores son del tipo String.
A primera vista, también podríamos clasificar «Dirección postal» como texto. Sin embargo, existen distintas formas de interpretar una dirección como esta. La primera palabra podría ser el nombre de un edificio o de una calle, mientras que los números que aparecen a continuación podrían indicar el número del inmueble o de su parcela. Las palabras siguientes podrían corresponder al barrio o a la ciudad. También es posible que la dirección comience con «Apartado postal», en cuyo caso ni siquiera indicaría un domicilio de entrega, sino únicamente un apartado de correspondencia en una oficina postal. Por lo tanto, cada parte de una dirección tiene un significado propio.
En principio, podríamos decir que una dirección es un String. De hecho, lo es, pero al tratarla únicamente como texto perderíamos información importante. Cuando definimos algo como String, indicamos que se trata de una simple secuencia de caracteres. En cambio, si podemos incluirlo en una categoría más específica, dispondremos de mucha más información sobre su contenido. Por ejemplo, si sabemos que un String representa una dirección, podremos interpretarlo y manipularlo de una manera más apropiada.
La misma lógica puede aplicarse a los números de teléfono. Podemos especificar un tipo llamado NumeroTelefono y, cuando encontremos un valor de ese tipo, podremos buscar patrones como los códigos de área o de país. Otra razón para no tratarlos como números comunes es que no tiene sentido realizar operaciones aritméticas con ellos: ¿qué esperamos obtener al multiplicar un NumeroTelefono por 100 o dividirlo por la mitad? Es posible que el resultado ni siquiera sea un número de teléfono válido. Además, no es aceptable perder, omitir ni redondear sus cifras por ese mismo motivo.
=== La utilidad de los tipos ===
Pero ¿por qué nos ayuda a programar separar y categorizar las cosas? Una vez definidos los tipos, podemos especificar qué operaciones se pueden realizar con sus valores y cuáles no. Esto resulta especialmente útil para evitar errores en programas extensos.
== Usando el comando interactivo <code>:type</code> ==
Exploremos el funcionamiento de los tipos mediante una sesión de GHCi. Podemos consultar el tipo de una expresión con el comando <code>:type</code> o su abreviatura <code>:t</code>. Probémoslo con valores booleanos y expresiones booleanas:
{{Haskell/GHCi|1=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
El símbolo <tt>::</tt> aparece en todos los resultados. Se lee como «es del tipo» y va seguido de una ''firma de tipo'' o ''anotación de tipo''.
El comando <code>:t</code> nos muestra que los valores verdadero (<code>True</code>) y falso (<code>False</code>) son del tipo <code>Bool</code>. Incluso las expresiones tienen un tipo definido: cuando se evalúan, producen un valor de tipo <code>Bool</code>. Quizá esto ya esté claro, pero conviene señalar que <code>Bool</code> es el tipo de dato elegido para representar valores de verdadero o falso. Por ejemplo, permite indicar si se encontró un valor o si se pulsó un botón.
== Caracteres y ''cadenas de caracteres'' ==
Probemos ahora <code>:t</code> con otros valores. En Haskell, un único carácter se representa encerrándolo entre comillas simples:
{{Haskell/GHCi|1=
Prelude> :t 'H'
'H' :: Char
}}
Por lo tanto, los caracteres son del tipo <code>Char</code>, abreviatura de ''character'' (carácter, en inglés). Para representar una cadena de caracteres en lugar de uno solo, debemos utilizar comillas dobles:
{{Haskell/GHCi|1=
Prelude> :t "Hola, mundo"
"Hola, mundo" :: [Char]
}}
De nuevo aparece <code>Char</code>, pero esta vez entre corchetes. <code>[Char]</code> significa una ''lista'' de caracteres. Haskell considera que toda cadena de caracteres es una lista. Las listas son muy importantes en Haskell, y hablaremos de ellas más adelante.
{{Haskell/Ejercicios|1=
# Usa <code>:type</code> seguido de un valor como <code>"H"</code> en GHCi. Observa que aquí utilizamos comillas dobles. ¿Qué sucede y por qué?
# Usa <code>:type</code> seguido de un valor como <code>'Hola, mundo'</code> en GHCi. Observa que aquí utilizamos comillas simples. ¿Qué sucede y por qué?
}}
Haskell nos permite crear ''sinónimos de tipos'', que funcionan como los sinónimos del lenguaje humano: palabras diferentes que tienen el mismo significado. Estos sinónimos son nombres alternativos para los tipos. Por ejemplo, <tt>String</tt> está definido como sinónimo de <tt>[Char]</tt>, por lo que podemos utilizar uno u otro indistintamente:
<syntaxhighlight lang="haskell">
"Hola, mundo" :: String
</syntaxhighlight>
El código anterior es perfectamente válido. Para las personas, resulta mucho más claro leer <code>String</code> que leer <code>[Char]</code> e interpretar que se trata de una lista de caracteres y, por lo tanto, de una cadena de caracteres.
== Tipos de las funciones ==
Hasta ahora hemos visto los tipos de algunos valores (cadenas de caracteres, valores booleanos, caracteres, etc.). También hemos visto que los tipos nos ayudan a categorizar y describir determinados valores de una forma más conveniente. Ahora veremos qué hace que el sistema de tipos de Haskell sea tan importante y poderoso: las ''funciones'' también tienen tipos.
=== Ejemplo ===
Podemos invertir un valor booleano mediante la función <code>not</code>, como ya vimos. Para conocer el tipo de una función, debemos tener en cuenta dos cosas: los tipos de sus argumentos y el tipo del valor que devuelve, es decir, el tipo de su salida. En el caso de <code>not</code>, es muy sencillo: recibe un valor de tipo <code>Bool</code> y devuelve otro del mismo tipo. En Haskell, utilizamos la siguiente notación:
<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>
Esta línea puede leerse así: «<tt>not</tt> es del tipo que recibe valores de tipo <tt>Bool</tt> y devuelve valores de tipo <tt>Bool</tt>». En otras palabras, es una función que transforma un valor de tipo <tt>Bool</tt> (la entrada) en otro de tipo <tt>Bool</tt> (la salida).
En GHCi también podemos utilizar <code>:t</code> con las funciones:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
Por lo tanto, el tipo de una función se describe mediante el tipo de su entrada y el de su salida.
=== Ejemplo: <code>chr</code> y <code>ord</code> ===
La representación del texto siempre ha sido un problema para las computadoras. En su nivel más básico, una computadora solo puede interpretar datos binarios: unos y ceros. Para representar un texto, cada carácter debe convertirse primero en un número, que después puede expresarse en forma binaria para que la computadora lo interprete. La conversión a binario es una tarea sencilla para la máquina, por lo que aquí solo nos interesa la conversión de un carácter a su representación numérica.
Una forma sencilla de realizar esta tarea sería enumerar todos los caracteres posibles. Por ejemplo, podríamos hacer corresponder la letra «a» con el número 1, la «b» con el 2, la «c» con el 3, y así sucesivamente. Haskell ya dispone de una codificación de caracteres, y sería tedioso consultar su tabla cada vez que necesitáramos conocer los valores numéricos. Por comodidad, contamos con dos funciones que realizan estas conversiones: <code>chr</code> y <code>ord</code>.<ref group="nota">No es exactamente así como funcionan <code>chr</code> y <code>ord</code>, pero esta descripción es válida por ahora.</ref> Investiguemos sus tipos:
<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>
Como ya sabemos qué significa <code>Char</code>, expliquemos <code>Int</code>. Este tipo representa números enteros y es solo uno de los varios tipos numéricos definidos en Haskell. De hecho, Haskell dispone de más de un tipo para representar números enteros. La firma de tipo de <code>chr</code> nos indica que recibe un argumento de tipo <code>Int</code>, es decir, un número entero, y produce un resultado de tipo <code>Char</code>. En el caso de <code>ord</code>, sucede lo contrario: recibe un argumento de tipo <code>Char</code> y devuelve uno de tipo <code>Int</code>. Al analizar ambas firmas, queda claro cuál de las funciones convierte un carácter en un número (<code>ord</code>) y cuál realiza la operación inversa (<code>chr</code>).
Veamos algunos ejemplos. Estas funciones no están disponibles de forma predeterminada al abrir una sesión de GHCi, por lo que debemos cargar el módulo <code>Data.Char</code>, donde están definidas, mediante el comando <code>:module Data.Char</code> o su abreviatura <code>:m</code>.
{{Haskell/GHCi|1=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Funciones con más de un argumento ===
¿Cuál sería el tipo de una función con más de un argumento?
<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
<code>xor</code> es la función lógica «o exclusivo», que evalúa si exactamente uno de sus argumentos es <code>True</code>. Si ambos son verdaderos o ambos son falsos, devuelve <code>False</code>.
El método básico para describir el tipo de una función con varios argumentos consiste en escribir los tipos de cada argumento en secuencia (primero el de <code>p</code>, después el de <code>q</code>, por ejemplo) y añadir al final el tipo del resultado. Después, basta con intercalar los tipos mediante el símbolo <code>-></code>.<ref group="nota">Trataremos este tema con más detalle en el capítulo sobre [[Haskell/Funciones de alta orden|funciones de orden superior]].</ref>
<ol>
<li>
Escribe los tipos de los argumentos de entrada en secuencia y, al final, el tipo de salida. La definición de <code>xor</code> nos indica que sus argumentos se evalúan como <code>True</code> o <code>False</code>. Por lo tanto, ambos deben ser del tipo <code>Bool</code>. La salida también es de tipo <code>Bool</code>:
<pre>
Bool Bool Bool
^^^^ p es de tipo Bool ^^^^ q es de tipo Bool ^^^^ la salida también es de tipo Bool
</pre>
</li>
<li>
Intercala los tipos mediante <code>-></code>:
<pre>Bool -> Bool -> Bool</pre>
</li>
</ol>
Por lo tanto, la firma de tipo de <code>xor</code> es:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>
Puede leerse así: «<tt>xor</tt> es del tipo que recibe dos valores <tt>Bool</tt> y devuelve un valor <tt>Bool</tt>».
=== Ejemplo: <code>abrirVentana</code> ===
{{Nota al margen|margen=derecha|Una biblioteca es una colección de código común utilizado por muchos programas.}}
A medida que profundizamos en nuestros conocimientos de programación, algunos términos técnicos se vuelven habituales. Uno de ellos es el de ''bibliotecas'', que son conjuntos de código destinados a un propósito determinado y que pueden utilizarse en distintos programas. Uno de los tipos de bibliotecas más comunes es el de las GUI (''<u>G</u>raphical <u>U</u>ser <u>I</u>nterface'', o «interfaz gráfica de usuario», en español). En este tipo de bibliotecas podemos encontrar funciones para crear botones y menús, así como para gestionar la interacción con el ratón y el teclado. Una posible función sería <code>abrirVentana</code>, que probablemente abriría una ventana nueva al ejecutarse. La firma de tipo de una función como esta podría ser:
<syntaxhighlight lang="haskell">
abrirVentana :: TituloVentana -> TamanioVentana -> Ventana
</syntaxhighlight>
No necesitamos conocer en profundidad la definición de estos tipos, pero sus nombres nos ayudan a entender qué se necesita para crear una ventana. También es muy probable que estén definidos en la propia biblioteca que contiene la función <code>abrirVentana</code>.
Analicémoslo por partes. Recordemos lo que explicamos en la [[#Funciones con más de un argumento|sección anterior]]: el último tipo descrito en la firma de una función es el de su salida. Por lo tanto, ¿cuántos argumentos necesita <code>abrirVentana</code>? Dos. ¿Cuáles son sus tipos? <code>TituloVentana</code> y <code>TamanioVentana</code>. ¿Y cuál es el tipo de la salida? <code>Ventana</code>. Así, podemos entender que «<code>abrirVentana</code> es una función que crea una ventana nueva y que, para hacerlo, necesita un título y un tamaño».
Observa que no es necesario haber utilizado una función para comprender qué hace. Cuando utilizamos tipos cuyos nombres son suficientemente claros, la firma de la función nos da pistas sobre su funcionamiento. Es una buena práctica probar las funciones con <code>:t</code> en GHCi antes de utilizarlas. Cuanto más lo hagas, mejor será tu intuición para interpretar los tipos de las funciones.
{{Haskell/Ejercicios|1=
Intenta deducir las anotaciones de tipo de las siguientes funciones. Si alguna de ellas involucra números, supón que son del tipo Int.
# <code>negativo</code>: una función que recibe un Int y devuelve su opuesto (con el signo invertido). Ejemplos: <code>negativo 4 = -4</code>; <code>negativo (-2) = 2</code>.
# <code><nowiki>||</nowiki></code>: la función lógica «o». Recibe dos valores booleanos y comprueba si al menos uno de ellos es verdadero. Si es así, devuelve verdadero; de lo contrario, devuelve falso.
# <code>diasEnElMes</code>: una función que calcula la cantidad de días de un mes determinado. Recibe un valor que indica si el año es bisiesto y el número del mes, del 1 al 12.
# <code>f x y = not x <nowiki>||</nowiki> y</code>
# <code>g x = (2*x - 1)^2</code>
}}
== Anotaciones de tipo en archivos de código ==
Ahora que ya comprendemos un poco qué son los tipos y cómo pueden ayudarnos, veamos cómo incluir este tipo de anotaciones en el código fuente de un programa. Consideremos la función <code>xor</code> que definimos anteriormente. Si queremos definirla en un archivo y anotar su tipo, basta con escribir lo siguiente:
<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>
Eso es todo. Para mayor claridad, es habitual colocar la anotación inmediatamente antes de la definición de la función, por lo que se recomienda seguir esta convención.
Además de facilitar la comprensión del funcionamiento de una función, las anotaciones de tipo también son fundamentales para que el compilador interprete correctamente el código, como veremos a continuación.
=== Inferencia de tipos ===
Como dijimos antes, las funciones tienen tipos. Es importante destacar que ''siempre'' los tienen. Entonces, ¿cómo pudimos escribir las funciones del capítulo anterior sin especificar ninguna firma? Esto es posible porque el compilador puede ''inferir'' el tipo de una función basándose en las operaciones que realiza. Veamos el siguiente caso:
<syntaxhighlight lang="haskell">
ehL c = c == 'l'
</syntaxhighlight>
<code>ehL</code> es una función que recibe un argumento, <code>c</code>, y devuelve el resultado de la expresión <code>c == 'l'</code>. Aunque no hayamos anotado explícitamente el tipo de <code>c</code> ni el de la salida, podemos intentar deducir la firma de tipo de <code>ehL</code>. Veamos cómo hacerlo:
* Es una función que recibe un argumento, <code>c</code>. Toda función en Haskell tiene una salida.
<pre>
_ -> _
</pre>
* La salida es el resultado de la operación <code>c == 'l'</code>. Como ya vimos, <code>(==)</code> es un operador de comparación de igualdad, y estas comparaciones suelen producir una respuesta de verdadero o falso, que puede representarse mediante el tipo <code>Bool</code>. De hecho, ya vimos el operador <code>(==)</code> en [[Haskell/Verdadero o falso|Verdadero o falso]], por lo que sabemos con certeza que su resultado es de tipo <code>Bool</code>.
<pre>
_ -> Bool
</pre>
* El operador <code>(==)</code> compara <code>c</code> con <code>'l'</code>. No tiene sentido comparar valores de tipos incompatibles. El valor <code>'l'</code> es de tipo <code>Char</code>, por lo que <code>c</code> también debe ser de ese tipo.
<pre>
Char -> Bool
</pre>
Si quieres comprobar lo que acabamos de deducir, define <code>ehL</code> en GHCi sin especificar una firma y utiliza después <code>:t</code> para consultar su tipo:
{{Haskell/GHCi|1=
Prelude> let ehL c = c == 'l'
Prelude> :t ehL
ehL :: Char -> Bool
}}
El compilador realiza un proceso bastante parecido para determinar el tipo de una función. Sin embargo, el resultado puede no ser la firma que esperas o deseas, e incluso puede ocurrir que no consiga determinar una firma válida. Por eso, se recomienda escribir siempre las anotaciones de tipo de las funciones:
<syntaxhighlight lang="haskell">
ehL :: Char -> Bool
ehL c = c == 'l'
</syntaxhighlight>
También existen otras buenas razones para incluirlas en el código:
* '''Documentación:''' como ya vimos, las anotaciones de tipo ayudan a comprender qué hace una función. ''Documentar'' un programa consiste precisamente en describir qué hacen sus partes y cómo funcionan. Por supuesto, los comentarios también ayudan, pero en Haskell las anotaciones de tipo son tan importantes como ellos.
* '''''Depuración'' (''debugging''):''' muchos errores de los programas, conocidos como ''bugs'', se producen al utilizar una función de manera incorrecta. Las anotaciones de tipo ayudan tanto al programador como al compilador a comprobar si una función se está utilizando correctamente, verificando los tipos de las entradas y salidas. Cuando declaramos las anotaciones y se produce un error de incompatibilidad de tipos, el compilador muestra un mensaje que indica dónde está el problema. Si omitimos los tipos, el compilador puede inferir una firma que funcione en una parte del programa, pero que provoque otros errores inesperados durante la ejecución o errores de compilación en otras partes.
Veamos un ejemplo sencillo de depuración. Prueba lo siguiente en GHCi:
{{Haskell/GHCi|1=
Prelude> "hola" ++ " mundo"
"hola mundo"
Prelude> "hola" + " mundo"
<interactive>:2:1: error:
* No instance for (Num [Char]) arising from a use of `+'
* In the expression: "hola" + " mundo"
In an equation for `it': it = "hola" + " mundo"
}}
Acabamos de introducir el operador <code>(++)</code>, que sirve para concatenar las dos cadenas de caracteres <code>"hola"</code> y <code>" mundo"</code>. Si, por un error de escritura, utilizamos <tt>+</tt> en lugar de <tt>++</tt>, aparecerá el mensaje de error anterior. En resumen, el mensaje nos indica que el operador <code>(+)</code> solo está definido para valores pertenecientes a la clase de tipos <code>Num</code>, mientras que estamos intentando aplicarlo a valores de tipo <code>[Char]</code>, es decir, cadenas de caracteres.
Es importante señalar que la comprobación de tipos no evita por completo todos los errores. De hecho, todavía podemos escribir una función de una manera que no produzca el resultado deseado. Sin embargo, reflexionar sobre las operaciones que podemos realizar con cada tipo de dato nos ayuda a razonar mejor sobre la lógica de nuestros programas.
== Notas ==
<references group="nota"/>
{{AutoCat}}
[[Categoría:Libro:Haskell]]
2bu1q31b16wm3spu4tdzv0bjos7qklj
Categoría:Haskell/Plantillas
14
65094
436490
2026-10-14T12:18:07Z
Luciérnaga de conocimiento
119502
Página creada con «[[Categoría:Libro:Haskell]]»
436490
wikitext
text/x-wiki
[[Categoría:Libro:Haskell]]
ru8trst303x18blgxzh6eb563blck26
Categoría:Libro:Plantilla:Haskell
14
65095
436492
2026-10-14T12:19:04Z
Luciérnaga de conocimiento
119502
Luciérnaga de conocimiento trasladó la página [[Categoría:Libro:Plantilla:Haskell]] a [[Categoría:Libro:Plantillas:Haskell]]
436492
wikitext
text/x-wiki
#REDIRECCIÓN [[:Categoría:Libro:Plantillas:Haskell]]
np0ellmjltr9h49dva47rwq7hr1x0dh
Categoría:Manual de LaTeX
14
65096
436568
2026-10-15T07:52:54Z
Antimundo
74354
Antimundo trasladó la página [[Categoría:Manual de LaTeX]] a [[Categoría:Libro:Manual de LaTeX]]: Política de nombrado
436568
wikitext
text/x-wiki
#REDIRECCIÓN [[:Categoría:Libro:Manual de LaTeX]]
fg10d1x3trgqyd4fziza0rptfea6fbt