#LyX 2.3 created this file. For more info see http://www.lyx.org/ \lyxformat 544 \begin_document \begin_header \save_transient_properties true \origin unavailable \textclass book \begin_preamble \input{../defs} \end_preamble \use_default_options true \maintain_unincluded_children false \language spanish \language_package default \inputencoding auto \fontencoding global \font_roman "default" "default" \font_sans "default" "default" \font_typewriter "default" "default" \font_math "auto" "auto" \font_default_family default \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 100 \font_tt_scale 100 100 \use_microtype false \use_dash_ligatures true \graphics default \default_output_format default \output_sync 0 \bibtex_command default \index_command default \paperfontsize default \spacing single \use_hyperref false \papersize default \use_geometry false \use_package amsmath 1 \use_package amssymb 1 \use_package cancel 1 \use_package esint 1 \use_package mathdots 1 \use_package mathtools 1 \use_package mhchem 1 \use_package stackrel 1 \use_package stmaryrd 1 \use_package undertilde 1 \cite_engine basic \cite_engine_type default \biblio_style plain \use_bibtopic false \use_indices false \paperorientation portrait \suppress_date false \justification true \use_refstyle 1 \use_minted 0 \index Index \shortcut idx \color #008000 \end_index \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \paragraph_indentation default \is_math_indent 0 \math_numbering_side default \quotes_style french \dynamic_quotes 0 \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict false \end_header \begin_body \begin_layout Standard Haskell es un lenguaje de programación funcional puro y perezoso. \end_layout \begin_layout Section Estructura léxica \begin_inset Foot status open \begin_layout Plain Layout Las reglas \family typewriter \emph on nombre \emph default =~ \emph on regex \family default \emph default definen una expresión regular en formato PCRE ampliado con dos reglas: que \family typewriter < \emph on nombre \emph default > \family default incluye la expresión regular nombrada entre paréntesis y que un \family typewriter \backslash \family default antes de un salto de línea se salta todos los caracteres desde él mismo hasta el primer caracter de la siguiente línea que no es un espacio en blanco. \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout program =~ (|)* \end_layout \begin_layout Plain Layout lexeme =~ ||||| \backslash \end_layout \begin_layout Plain Layout || \end_layout \begin_layout Plain Layout whitespace =~ + \end_layout \begin_layout Plain Layout whitestuff =~ || \end_layout \begin_layout Plain Layout whitechar =~ |[ \backslash v \backslash t]| \backslash p{Separator} \end_layout \begin_layout Plain Layout newline =~ \backslash r \backslash n|[ \backslash r \backslash n \backslash f] \end_layout \begin_layout Plain Layout comment =~ --+(?!)* \end_layout \begin_layout Plain Layout ncomment =~ \backslash {-()*- \backslash } \end_layout \end_inset \end_layout \begin_layout Standard Las clases de caracteres son: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout anyseq =~ (?!*( \backslash {-|- \backslash })*)* \end_layout \begin_layout Plain Layout any =~ | \end_layout \begin_layout Plain Layout anynb =~ |[ \backslash t] \end_layout \begin_layout Plain Layout graphic =~ |||||[ \begin_inset Quotes cld \end_inset '] \end_layout \begin_layout Plain Layout small =~ \backslash p{Lowercase_Letter}|_ \end_layout \begin_layout Plain Layout large =~ \backslash p{Uppercase_Letter}| \backslash p{Titlecase_Letter} \end_layout \begin_layout Plain Layout symbol =~ [!#$%&*+./<=>?@ \backslash \backslash ^|~:-]|(?!|[_ \begin_inset Quotes crd \end_inset ']) \backslash p{Symbol} \end_layout \begin_layout Plain Layout digit =~ \backslash p{Decimal_Digit_Number} \end_layout \begin_layout Plain Layout octit =~ [0-7] \end_layout \begin_layout Plain Layout hexit =~ |[A-Fa-f] \end_layout \begin_layout Plain Layout special =~ [() \backslash [ \backslash ]{},;`] \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \end_layout \begin_layout Standard Las palabras reservadas son: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout reservedid =~ case|class|data|default|deriving|do|else|foreign| \backslash \end_layout \begin_layout Plain Layout if|import|in|infix|infixl|infixr|instance|let| \backslash \end_layout \begin_layout Plain Layout module|newtype|of|then|type|where|_ \end_layout \begin_layout Plain Layout reservedop =~ \backslash . \backslash .|:|::|=| \backslash \backslash | \backslash ||<-|->|@|~|=> \end_layout \end_inset \end_layout \begin_layout Standard Las variables pueden estar en espacios de nombres aparentemente jerárquicos: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout qvarid =~ ( \backslash .)* \end_layout \begin_layout Plain Layout qconid =~ ( \backslash .)* \end_layout \begin_layout Plain Layout qvarsym =~ ( \backslash .)* \end_layout \begin_layout Plain Layout qconsym =~ ( \backslash .)* \end_layout \end_inset \end_layout \begin_layout Standard Realmente sólo se distingue entre el nombre de la variable, detrás del último \family typewriter . \family default , y el del módulo, antes del \family typewriter . \family default , y no hay relación jerárquica entre módulos. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout varid =~ (?!(?!|||')) \backslash \end_layout \begin_layout Plain Layout (|||')* \end_layout \begin_layout Plain Layout conid =~ (|||')* \end_layout \begin_layout Plain Layout varsym =~ (?!((--+|)(?!))|:)+ \end_layout \begin_layout Plain Layout consym =~ (?!(?!)):* \end_layout \end_inset \end_layout \begin_layout Standard Los literales son: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout literal =~ ||| \end_layout \begin_layout Plain Layout integer =~ +|0[oO]+|0[xX]+ \end_layout \begin_layout Plain Layout float =~ + \backslash .+()?|+ \end_layout \begin_layout Plain Layout exponent =~ [eE][+-]?+ \end_layout \begin_layout Plain Layout char =~ '((?![' \backslash \backslash ])| |(?! \backslash \backslash &))' \end_layout \begin_layout Plain Layout string =~ \begin_inset Quotes cld \end_inset ((?![ \begin_inset Quotes cld \end_inset \backslash \backslash ])| || \backslash \backslash + \backslash \backslash )* \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout escape =~ \backslash \backslash (|||o+|x+) \end_layout \begin_layout Plain Layout charesc =~ [abfnrtv \backslash \backslash \begin_inset Quotes crd \end_inset '&] \end_layout \begin_layout Plain Layout ascii =~ \backslash ^[A-Z@ \backslash [ \backslash ] \backslash \backslash ^_]|NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS| \backslash \end_layout \begin_layout Plain Layout HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB| \backslash \end_layout \begin_layout Plain Layout CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL \end_layout \end_inset \end_layout \begin_layout Standard En principio un programa se interpreta como una secuencia de lexemas, \family typewriter { \family default entra en un nuevo contexto y \family typewriter } \family default sale del último contexto en que se ha entrado. Sin embargo, se pueden evitar apariciones de \family typewriter { \family default , \family typewriter } \family default y \family typewriter ; \family default sangrando los lexemas de cierta forma y dejando que el \emph on \lang english lexer \emph default \lang spanish los inserte como sigue: \end_layout \begin_layout Enumerate Tras un \family typewriter let \family default , \family typewriter where \family default , \family typewriter do \family default u \family typewriter of \family default no seguido de \family typewriter { \family default , o al principio del cuerpo si este no empieza por \family typewriter module \family default o \family typewriter { \family default , se inserta \family typewriter { \family default y se abre un contexto implícito desde la columna por la que empieza el siguiente lexema (si lo hay). Este se cierra inmediatamente insertando \family typewriter } \family default si está directamente dentro (sin ningún contexto \begin_inset Quotes cld \end_inset en medio \begin_inset Quotes crd \end_inset ) de un contexto implícito que empieza en una columna anterior. \end_layout \begin_layout Enumerate Si el primer lexema explícito en una línea no es el primero de su contexto, mientras su contexto sea implícito, justo antes de la línea se inserta \family typewriter ; \family default si el lexema empieza en la misma columna que el contexto o \family typewriter } \family default y si empieza en una anterior, cerrando el contexto. \end_layout \begin_layout Enumerate Es un error cerrar un contexto implícito con un \family typewriter } \family default explícito. \end_layout \begin_layout Enumerate Mientras un lexema explícito en un contexto implícito cause un error sintáctico (los lexemas explícitos o implícitos anteriores forman un prefijo válido de la gramática libre de contexto pero al añadir el propio lexema ya no), se inserta \family typewriter } \family default antes del lexema. \end_layout \begin_layout Enumerate Al final de la entrada se insertan \family typewriter } \family default suficientes para cerrar los contextos implícitos que queden abiertos. \end_layout \begin_layout Section Sesiones \end_layout \begin_layout Standard El programa \family typewriter ghci \family default lee expresiones o definiciones en Haskell, una por línea o entre una línea \begin_inset Quotes cld \end_inset \family typewriter :{ \family default \begin_inset Quotes crd \end_inset y una \begin_inset Quotes cld \end_inset \family typewriter :} \family default \begin_inset Quotes crd \end_inset , las evalúa e imprime el resultado, y también puede interpretar comandos de \family typewriter ghci \family default . Una \series bold sesión \series default es la secuencia de interacciones entre el usuario y este programa. Las definiciones también se pueden guardar en ficheros, generalmente con extensión \family typewriter .hs \family default , llamadas \series bold guiones \series default o \series bold \emph on \lang english scripts \series default \emph default \lang spanish , que se pueden cargar en el intérprete con el comando \family typewriter :l \emph on fichero \family default \emph default . El formato es: \begin_inset Foot status open \begin_layout Plain Layout Las reglas \family typewriter \emph on nombre \emph default = \emph on valor \family default \emph default describen la gramática libre de contexto de Haskell en ABNF, con la extensión de que \family typewriter ! \emph on x \family default \emph default indica que el siguiente elemento no debe tener forma \family typewriter \emph on x \family default \emph default . Cada cadena entre comillas representa un sólo lexema y entre dos lexemas puede haber espacio. Esta gramática tiene ambigüedades que se resuelven haciendo las frases tan largas como sea posible de izquierda a derecha, resolviendo todos los conflictos \emph on \lang english shift-reduce \emph default \lang spanish con \emph on \lang english shift \emph default \lang spanish . Los \emph on \lang english tokens \emph default \lang spanish también se extienden lo máximo posible. \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout module = body \end_layout \begin_layout Plain Layout body = \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset topdecls \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout topdecls = [topdecl *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset topdecl)] \end_layout \begin_layout Plain Layout topdecl = decl \end_layout \end_inset \end_layout \begin_layout Standard Un \series bold vínculo \series default es una asignación de un nombre a un valor, y un \series bold entorno \series default o \series bold contexto \series default es un conjunto de vínculos en que no hay más de un vínculo para el mismo nombre. Las expresiones se evalúan en un cierto contexto, y describen un valor que depende de este. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout var = varid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset varsym \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout varop = varsym / \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset varid \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout con = conid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset consym \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout conop = consym / \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset conid \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qvar = qvarid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset qvarsym \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qvarop = qvarsym / \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset qvarid \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qcon = qconid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset gconsym \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qconop = gconsym / \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset qconid \begin_inset Quotes cld \end_inset ` \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout gconsym = qconsym \end_layout \begin_layout Plain Layout cname = var / con \end_layout \begin_layout Plain Layout qop = qvarop / qconop \end_layout \end_inset \end_layout \begin_layout Standard Las variables se nombran como \family typewriter varid \family default y los \series bold operadores \series default infijos como \family typewriter varsym \family default , pero es posible usar un operador como nombre normal poniéndolo entre paréntesi s y una función con nombre normal como operador poniéndola entre comillas invertidas. Se pueden definir nuevos operadores. \end_layout \begin_layout Standard En el resto del capítulo cuando se menciona un nombre concreto, salvo que se indique lo contrario, se entiende que pertenece al módulo \family typewriter \lang english Prelude \family default \lang spanish , el \series bold preludio estándar \series default , cuyos vínculos están por defecto en el contexto global. \end_layout \begin_layout Section Tipos \end_layout \begin_layout Standard Todo valor tiene un tipo con un cierto dominio, que incluye un \series bold valor indefinido \series default \begin_inset Formula $\bot$ \end_inset correspondiente a las expresiones de ese tipo cuya evaluación no termina, aunque también se usa para notificar errores. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout type = btype [ \begin_inset Quotes cld \end_inset -> \begin_inset Quotes crd \end_inset type] \end_layout \begin_layout Plain Layout btype = [btype] atype \end_layout \begin_layout Plain Layout atype = gtycon / varid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset type \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout gtycon = qconid \end_layout \end_inset \end_layout \begin_layout Standard Un tipo puede ser un \family typewriter qconid \family default , cuyo significado depende del entorno, y esta definición puede aceptar un número fijo de parámetros de tipo. \end_layout \begin_layout Standard El tipo \family typewriter \emph on fuente \emph default -> \emph on \begin_inset space ~ \end_inset resultado \family default \emph default es el de las funciones que toman \series bold argumentos \series default del \series bold tipo fuente \series default y devuelven \series bold resultados \series default del \series bold tipo resultado \series default . Una función \begin_inset Formula $f$ \end_inset es \series bold estricta \series default si \begin_inset Formula $f\,\bot=\bot$ \end_inset . Dos funciones son \series bold iguales \series default si devuelven los mismos resultados para los mismos argumentos, y entonces el compilador es libre de cambiar una por otra. Normalmente las funciones están currificadas, pues esto reduce el número de paréntesis y permite aplicar una función de varios argumentos a menos argumentos para obtener otra función que puede ser útil por sí misma. Es idiomático \begin_inset Formula $\eta$ \end_inset -reducir las definiciones de funciones. \end_layout \begin_layout Standard Un \family typewriter varid \family default representa una variable libre, y cuando el tipo que se asigna a una expresión tiene alguna variable libre, el tipo de la expresión es \series bold polimórfico \series default , genérico sobre los valores de las variables libres. \end_layout \begin_layout Standard Tipos primitivos en el \family typewriter \lang english Prelude \family default \lang spanish : \end_layout \begin_layout Description \family typewriter Char \family default Caracteres Unicode. \end_layout \begin_layout Description \family typewriter Double \family default Números de punto flotante de precisión doble. \end_layout \begin_layout Description \family typewriter Float \family default Números de punto flotante de precisión simple. \end_layout \begin_layout Description \family typewriter Int \begin_inset space ~ \end_inset = \begin_inset space ~ \end_inset minBound \begin_inset space ~ \end_inset ... \begin_inset space ~ \end_inset -1 \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset 0 \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset 1 \begin_inset space ~ \end_inset ... \begin_inset space ~ \end_inset maxBound \family default Enteros de tamaño limitado, con al menos los del rango \begin_inset Formula $[-2^{29},2^{29})$ \end_inset . \end_layout \begin_layout Description \family typewriter Integer \begin_inset space ~ \end_inset = \begin_inset space ~ \end_inset ... \begin_inset space ~ \end_inset -1 \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset 0 \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset 1 \begin_inset space ~ \end_inset ... \family default Enteros de tamaño arbitrario. \end_layout \begin_layout Standard También son predefinidos las \series bold tuplas \series default , productos directos de un número fijo de tipos escritos entre paréntesis, las \series bold listas \series default , secuencias finitas de elementos del mismo tipo, escrito entre corchetes, y el \series bold tipo unidad \series default \family typewriter () \family default , con un solo elemento: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout atype /= \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset type 1*( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset type) \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset type \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout gtycon /= \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset Podemos definir nuevos tipos para aumentar la seguridad de los programas: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout topdecl /= \begin_inset Quotes cld \end_inset data \begin_inset Quotes crd \end_inset [context \begin_inset Quotes cld \end_inset => \begin_inset Quotes crd \end_inset ] simpletype \begin_inset Quotes cld \end_inset = \begin_inset Quotes crd \end_inset constrs \end_layout \begin_layout Plain Layout [deriving] \end_layout \begin_layout Plain Layout constrs = constr *( \begin_inset Quotes cld \end_inset | \begin_inset Quotes crd \end_inset constr) \end_layout \begin_layout Plain Layout constr = conid *atype \end_layout \begin_layout Plain Layout / (btype / \begin_inset Quotes cld \end_inset ! \begin_inset Quotes crd \end_inset atype) conop (btype / \begin_inset Quotes cld \end_inset ! \begin_inset Quotes crd \end_inset atype) \end_layout \begin_layout Plain Layout simpletype = conid *varid \end_layout \end_inset \end_layout \begin_layout Standard Cada \family typewriter constr \family default se refiere al tipo producto de los \family typewriter atype \family default o \family typewriter btype \family default etiquetado con el \family typewriter conid \family default o \family typewriter conop \family default , o bien a un tipo unipuntual con nombre \family typewriter conid \family default , y el tipo \family typewriter simpletype \family default es la unión disjunta de estos tipos producto y de \begin_inset Formula $\{\bot\}$ \end_inset . Si \family typewriter simpletype \family default contiene variables, estas corresponden a parámetros de tipo, y los \family typewriter constrs \family default solo pueden contener variables que aparezcan en el \family typewriter simpletype \family default . El \family typewriter \lang english Prelude \family default \lang spanish define \family typewriter data Bool = False | True \family default . \end_layout \begin_layout Standard También es posible añadir nombres a los campos: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout constr /= con \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset [fielddecl *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset fielddecl)] \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout fielddecl = vars \begin_inset Quotes cld \end_inset :: \begin_inset Quotes crd \end_inset (type / \begin_inset Quotes cld \end_inset ! \begin_inset Quotes crd \end_inset atype) \end_layout \begin_layout Plain Layout vars = var *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset var) \end_layout \end_inset \end_layout \begin_layout Standard Cada \family typewriter var \family default define un campo del tipo producto, y por cada una se crea una función del tipo definido al tipo de la variable, que devuelve el valor en esa posición si la variable es de la variante \family typewriter con \family default o \begin_inset Formula $\bot$ \end_inset en otro caso. Un \series bold tipo recursivo \series default es uno que se tiene a sí mismo en la parte derecha de la definición, consiguien do valores recursivos. \end_layout \begin_layout Standard Los \series bold sinónimos de tipo \series default permiten definir abreviaturas para tipos comunes, que internamente se expanden al tipo a la derecha: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout topdecl /= \begin_inset Quotes cld \end_inset type \begin_inset Quotes crd \end_inset simpletype \begin_inset Quotes cld \end_inset = \begin_inset Quotes crd \end_inset type \end_layout \end_inset \end_layout \begin_layout Standard Las cadenas de caracteres se definen como \family typewriter type String = [Char] \family default . \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout topdecl /= \begin_inset Quotes cld \end_inset newtype \begin_inset Quotes crd \end_inset [context \begin_inset Quotes cld \end_inset => \begin_inset Quotes crd \end_inset ] simpletype = newconstr [deriving] \end_layout \begin_layout Plain Layout newconstr = con atype / con \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset var \begin_inset Quotes cld \end_inset :: \begin_inset Quotes crd \end_inset type \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Crea un tipo que etiqueta a otro. Equivale a cambiar \family typewriter newtype \family default por \family typewriter data \family default pero sin añadir un \begin_inset Formula $\bot$ \end_inset adicional. \end_layout \begin_layout Section Clases de tipos \end_layout \begin_layout Standard Son una forma de polimorfismo basada en clases cuyas instancias son tipos: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout topdecl /= \begin_inset Quotes cld \end_inset class \begin_inset Quotes crd \end_inset [scontext \begin_inset Quotes cld \end_inset => \begin_inset Quotes crd \end_inset ] conid varid [ \begin_inset Quotes cld \end_inset where \begin_inset Quotes crd \end_inset cdecls] \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset instance \begin_inset Quotes crd \end_inset [scontext \begin_inset Quotes cld \end_inset => \begin_inset Quotes crd \end_inset ] qconid inst [ \begin_inset Quotes cld \end_inset where \begin_inset Quotes crd \end_inset idecls] \end_layout \begin_layout Plain Layout cdecls = \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset [cdecl *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset cdecl) \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout inst = gtycon / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset gtycon *varid \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset varid 1*( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset varid) \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset varid \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset varid \begin_inset Quotes cld \end_inset -> \begin_inset Quotes crd \end_inset varid \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout idecls = \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset [idecl *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset idecl)] \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Una declaración \family typewriter class \family default define una clase \family typewriter conid \family default y una serie de vínculos en el contexto global dados por las asignaciones de tipo en las \family typewriter cdecl \family default , en las que \family typewriter varid \family default se refiere a un tipo cualquiera de clase \family typewriter conid \family default y debe aparecer alguna vez en el tipo asignado. Una \series bold declaración de instancia \series default \family typewriter instance \family default indica que el tipo \family typewriter inst \family default es de la clase \family typewriter qconid \family default y da las definiciones, llamadas \series bold métodos \series default , de los vínculos establecidos por la clase cuando el tipo \family typewriter varid \family default se sustituye por \family typewriter inst \family default . Los nombres de métodos son miembros de una única clase, lo que evita conflictos entre nombres. \end_layout \begin_layout Standard La declaración \family typewriter class \family default puede contener definiciones por defecto para los vínculos, en cuyo caso no es necesario dar estas definiciones en las instancias, y también puede declarar la aridad de operadores definidos en la clase. Sin embargo, es común que las definiciones por defecto estén unas en función de otras y haya que definir al menos un elemento para romper el ciclo. La \series bold definición mínima completa \series default de una clase es cualquier conjunto minimal de definiciones de la clase que deben definir las instancias. \end_layout \begin_layout Standard Las declaraciones pueden tener un \series bold contexto \series default para restringir los valores por los que se pueden sustituir las variables de tipo: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout context = class / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [class *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset class)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout class = qconid varid / qconid \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset varid 1*atype \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout scontext = simpleclass / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [simpleclass *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset simpleclass)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout simpleclass = qconid varid \end_layout \end_inset \end_layout \begin_layout Standard Las sustituciones deben respetar que cada \family typewriter varid \family default o \family typewriter varid 1*atype \family default sea de la clase \family typewriter qconid \family default . Esto es necesario cuando en la definición de una función se quieren usar funciones definidas en una clase, y de hecho el tipo de estas funciones en el entorno global tiene una restricción en su contexto. \end_layout \begin_layout Standard Si una clase \family typewriter class \family default ... \family typewriter => \emph on \begin_inset space ~ \end_inset Foo a \family default \emph default tiene \family typewriter \emph on Bar a \family default \emph default en su contexto, \family typewriter \emph on Bar \family default \emph default es \series bold superclase \series default de \family typewriter \emph on Foo \family default \emph default y \family typewriter \emph on Foo \family default \emph default es \series bold subclase \series default de \family typewriter \emph on Bar \family default \emph default , y todo contexto que indique que una variable o expresión tiene tipo \family typewriter \emph on Foo \family default \emph default permite usar sobre ella además de las operaciones de \family typewriter \emph on Foo \family default \emph default las de \family typewriter \emph on Bar \family default \emph default , recursivamente. El contexto de un método no puede tener restricciones sobre la variable de la clase. \end_layout \begin_layout Standard Se pueden derivar automáticamente las definiciones de algunas clases predefinida s: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout deriving = \begin_inset Quotes cld \end_inset deriving \begin_inset Quotes crd \end_inset (qconid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [qconid *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset qconid)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Haskell soporta \series bold tipos de alto rango \series default , lo que significa que las instancias de una clase pueden ser tipos que acepten parámetros, y no necesariamente tipos completos. \end_layout \begin_layout Section Expresiones \end_layout \begin_layout Standard Haskell tiene \series bold disciplina de tipos \series default , consistente en que toda expresión bien formada tiene un tipo deducible a partir de sus subexpresiones y los tipos de los vínculos en el contexto, y las expresiones a las que no se puede asignar un tipo están mal formadas. Esto permite detectar errores antes de la evaluación y fuerza al programador a plantearse tipos apropiados para los valores, ayudando a diseñar programas claros y bien estructurados. \end_layout \begin_layout Standard Al empezar a evaluar una expresión, primero se comprueba que la sintaxis sea correcta y, si no lo es, se produce un \series bold error de sintaxis \series default , y luego se comprueba si tiene un tipo correcto y si no se produce un \series bold error de tipo \series default . \end_layout \begin_layout Standard La \series bold evaluación ansiosa \series default o \series bold llamada por valor \series default es como el orden aplicativo pero sin evaluar en el interior de abstracciones, y la \series bold evaluación perezosa \series default o \series bold llamada por nombre \series default es como el orden normal pero sin evaluar en el interior de abstracciones. Haskell usa evaluación perezosa, que al contrario que la ansiosa garantiza la terminación si la expresión es normalizable. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout exp = infixexp [ \begin_inset Quotes cld \end_inset :: \begin_inset Quotes crd \end_inset type] \end_layout \begin_layout Plain Layout infixexp = lexp qop infixexp / \begin_inset Quotes cld \end_inset - \begin_inset Quotes crd \end_inset infixexp / lexp \end_layout \begin_layout Plain Layout lexp = fexp \end_layout \begin_layout Plain Layout fexp = [fexp] aexp / \begin_inset Quotes cld \end_inset let \begin_inset Quotes crd \end_inset decls \begin_inset Quotes cld \end_inset in \begin_inset Quotes crd \end_inset exp \end_layout \begin_layout Plain Layout aexp = qvar / literal / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset exp \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qvar = qvarid / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset qvarsym \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout decls = \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset [decl *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset decl)] \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Una variable ( \family typewriter qvar \family default ) representa su valor en el contexto; un \family typewriter literal \family default se representa a sí mismo; \family typewriter fexp aexp \family default representa la aplicación de la función \family typewriter fexp \family default al valor \family typewriter aexp \family default ; \family typewriter lexp qop infixexp \family default equivale a \family typewriter (qop) lexp infixexp \family default , aunque realmente distintos operadores tienen distinta precedencia del 0 al 9 y asociatividad por la izquierda o la derecha. \end_layout \begin_layout Standard La negación \family typewriter - \emph on a \family default \emph default equivale a \family typewriter negate \emph on a \family default \emph default ; los literales \family typewriter char \family default son de tipo \family typewriter Char \family default ; los \family typewriter string \family default de tipo \family typewriter String \family default ; los \family typewriter integer \family default equivalen a \family typewriter fromInteger ( \emph on x \emph default :: Integer) \family default , siendo \family typewriter \emph on x \family default \emph default el entero indicado, y los \family typewriter float \family default a \family typewriter fromRational ( \emph on x \emph default :: Data.Ratio.Rational) \family default . \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout aexp /= \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset exp 1*( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset exp) \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset exp *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset exp) \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset / gcon \end_layout \begin_layout Plain Layout gcon = \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset / qcon \end_layout \begin_layout Plain Layout gconsym /= \begin_inset Quotes cld \end_inset : \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard La primera sintaxis indica una tupla, la segunda una lista de un tamaño dado, \family typewriter () \family default el único elemento del tipo unidad, \family typewriter [] \family default la lista vacía y un \family typewriter qconid \family default es un constructor de tipo, que actúa como una función currificada que recibe tantos parámetros como aparezcan en su definición y del tipo correcto y devuelve un elemento del tipo correspondiente. Finalmente, \family typewriter (:) :: a -> [a] -> [a] \family default es un operador asociativo por la derecha con precedencia 5 que añade un elemento al inicio de una lista, con lo que \family typewriter [ \emph on a1 \emph default , \family default ... \family typewriter , \emph on an \emph default ] \family default equivale a \family typewriter \emph on a1 \emph default : \family default ... \family typewriter : \emph on an \emph default :[] \family default . \end_layout \begin_layout Standard Una \series bold sección \series default es un operador con una expresión delante o detrás: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout aexp /= \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset infixexp qop \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset ! \begin_inset Quotes crd \end_inset - \begin_inset Quotes crd \end_inset qop infixexp \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{sloppypar} \end_layout \end_inset \family typewriter ( \emph on infixexp qop \emph default ) \family default equivale a \family typewriter \backslash y -> \begin_inset space ~ \end_inset \emph on infixexp qop \emph default y \family default y \family typewriter ( \emph on qop infixexp \emph default ) \family default a \family typewriter \backslash x -> \begin_inset space ~ \end_inset x \emph on qop infixexp \family default \emph default . \begin_inset ERT status open \begin_layout Plain Layout \backslash end{sloppypar} \end_layout \end_inset \end_layout \begin_layout Section Patrones \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout pat = lpat / lpat qconop pat \end_layout \begin_layout Plain Layout lpat = apat / \begin_inset Quotes cld \end_inset - \begin_inset Quotes crd \end_inset (integer / float) / gcon 1*apat \end_layout \begin_layout Plain Layout apat = var [ \begin_inset Quotes cld \end_inset @ \begin_inset Quotes crd \end_inset apat] / literal / \begin_inset Quotes cld \end_inset _ \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset pat \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / gcon \end_layout \begin_layout Plain Layout / qcon \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset [fpat *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset fpat)] \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset pat 1*( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset pat) \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset pat *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset pat) \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout fpat = qvar \begin_inset Quotes cld \end_inset = \begin_inset Quotes crd \end_inset pat \end_layout \end_inset \end_layout \begin_layout Standard Un \series bold patrón \series default recibe un argumento y bien encaja, creando una serie de vínculos, o no. El patrón \family typewriter _ \family default siempre encaja y no crea vínculos; una variable siempre encaja y crea un vínculo de la variable al argumento; un patrón de forma \family typewriter \emph on var \emph default @ \emph on apat \family default \emph default es similar pero solo encaja si lo hace \family typewriter \emph on apat \family default \emph default y en tal caso crea un vínculo de \family typewriter \emph on var \family default \emph default al argumento que se añade a los vínculos que crea \family typewriter \emph on apat \family default \emph default . Una misma variable no puede aparecer dos veces en la misma lista de patrones, ni siquiera como subpatrón. Un literal, su negación o un \family typewriter gcon \family default suelto recibe un argumento del tipo que tendría como expresión, no crea vínculos y encaja sólo si el argumento es igual a él. \end_layout \begin_layout Standard Un patrón \family typewriter qcon 1*apat \family default , con tantos \family typewriter apat \family default como parámetros tenga el constructor \family typewriter qcon \family default , acepta un argumento del tipo que crearía el constructor y encaja si este es de la variante dada y cada \family typewriter apat \family default encaja con el elemento correspondiente de la variante, añadiendo los vínculos de los \family typewriter apat \family default . Uno \family typewriter qcon { \family default ... \family typewriter } \family default es similar pero para constructores definidos con llaves, y \family typewriter ( \family default ... \family typewriter ) \family default y \family typewriter [ \family default ... \family typewriter ] \family default hacen lo propio con tuplas y listas, entendiendo que las listas deben tener tantos elementos como patrones haya para encajar. \end_layout \begin_layout Standard Un patrón no estándar es \family typewriter varid \begin_inset Quotes qld \end_inset + \begin_inset Quotes qrd \end_inset integer \family default , que encaja con un entero de valor mayor o igual al \family typewriter integer \family default y asigna a la variable el entero menos ese \family typewriter integer \family default . \end_layout \begin_layout Standard Dada una lista de patrones o de listas de patrones del mismo tamaño cada una con una expresión asociada, el \series bold encaje de patrones \series default consiste en seleccionar la expresión correspondiente al primer patrón que encaje con cierto argumento, o la primera lista en que cada patrón encaje con el correspondiente argumento de una lista de argumentos. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout fexp /= \begin_inset Quotes cld \end_inset case \begin_inset Quotes crd \end_inset exp \begin_inset Quotes cld \end_inset of \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset alts \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset / \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset if \begin_inset Quotes crd \end_inset exp [ \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset ] \begin_inset Quotes cld \end_inset then \begin_inset Quotes crd \end_inset exp [ \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset ] \begin_inset Quotes cld \end_inset else \begin_inset Quotes crd \end_inset exp / \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset \backslash \backslash \begin_inset Quotes crd \end_inset 1*apat \begin_inset Quotes cld \end_inset -> \begin_inset Quotes crd \end_inset exp \end_layout \begin_layout Plain Layout alts = alt *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset alt) \end_layout \begin_layout Plain Layout alt = pat ( \begin_inset Quotes cld \end_inset -> \begin_inset Quotes crd \end_inset exp / 1*gdpat) [ \begin_inset Quotes cld \end_inset where \begin_inset Quotes crd \end_inset decls] \end_layout \begin_layout Plain Layout gdpat = guards \begin_inset Quotes cld \end_inset -> \begin_inset Quotes crd \end_inset exp \end_layout \begin_layout Plain Layout guards = \begin_inset Quotes cld \end_inset | \begin_inset Quotes crd \end_inset guard \end_layout \begin_layout Plain Layout guard = infixexp \end_layout \end_inset \end_layout \begin_layout Standard Si todas las \family typewriter alt \family default son del segundo tipo, \family typewriter case \emph on exp \emph default of \emph on alts \family default \emph default evalúa \family typewriter \emph on exp \family default \emph default ; selecciona la primera \family typewriter gdpat \family default tal que \family typewriter \emph on exp \family default \emph default encaja con el patrón de la \family typewriter alt \family default en la que está y, en un contexto extendido por las declaraciones en \family typewriter decls \family default y los vínculos de dicho patrón, la \series bold guarda \series default ( \family typewriter guard \family default ) devuelve \family typewriter True \family default , y finalmente evalúa la expresión del \family typewriter gdpat \family default en el contexto extendido y devuelve su valor, o bien devuelve \begin_inset Formula $\bot$ \end_inset si ninguna \family typewriter gdpat \family default cumple la condición. Una \family typewriter alt \family default de la forma \family typewriter -> \begin_inset space ~ \end_inset \emph on exp \family default \emph default equivale a \family typewriter | True -> \begin_inset space ~ \end_inset \emph on exp \family default \emph default . Todas las guardas deben tener tipo \family typewriter Bool \family default y todas las partes derechas de \family typewriter gdpat \family default o \family typewriter alt \family default de la misma \family typewriter case \family default deben tener el mismo tipo o intersección no vacía, y el tipo de la expresión \family typewriter case \family default será la intersección de los tipos de las partes derechas. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{sloppypar} \end_layout \end_inset \family typewriter if \emph on condition \emph default then \emph on when-true \emph default else \emph on when-false \family default \emph default equivale a \family typewriter case \emph on condition \emph default of { True -> \begin_inset space ~ \end_inset \emph on when-true \emph default ; False -> \begin_inset space ~ \end_inset \emph on when-false \emph default } \family default . \begin_inset ERT status open \begin_layout Plain Layout \backslash end{sloppypar} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \backslash \emph on apat \begin_inset Formula $_{1}$ \end_inset \emph default \family default ... \family typewriter \emph on apat \begin_inset Formula $_{n}$ \end_inset \emph default -> \emph on exp \family default \emph default representa una función con parámetros definidos por patrones (generalmente variables) cuya aplicación a \begin_inset Formula $n$ \end_inset parámetros encaja los parámetros si es posible y devuelve el valor de \family typewriter \emph on exp \family default \emph default en un contexto extendido por los vínculos creados por los patrones, y devuelve \begin_inset Formula $\bot$ \end_inset en otro caso. El tipo de los parámetros puede ser restringido por los patrones y los usos que se les da a las variables en \family typewriter \emph on exp \family default \emph default , y el tipo de la función es de la forma [ \family typewriter \emph on contexto \emph default => \family default ] \family typewriter \emph on t \begin_inset Formula $_{1}$ \end_inset -> \emph default \begin_inset space ~ \end_inset \family default ... \family typewriter \emph on -> \emph default \begin_inset space ~ \end_inset \emph on t \begin_inset Formula $_{n}$ \end_inset \emph default -> \begin_inset space ~ \end_inset \emph on r \family default \emph default , donde los \family typewriter \emph on t \begin_inset Formula $_{i}$ \end_inset \family default \emph default son los tipos de los parámetros, que pueden contener variables posiblemente restringidas por el \family typewriter \emph on contexto \family default \emph default , y \family typewriter \emph on r \family default \emph default es el tipo que tiene el resultado cuando las variables tienen los tipos dados por los \family typewriter \emph on t \begin_inset Formula $_{i}$ \end_inset \family default \emph default . Los \begin_inset Formula $\text{\emph{\texttt{t}}}_{i}$ \end_inset y el contexto son los más generales posibles para que los patrones y la expresión sean legales, salvo que se asigne un tipo más restringido. \end_layout \begin_layout Section Otras expresiones \end_layout \begin_layout Standard Una \series bold secuencia aritmética \series default se define como: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout aexp /= \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset exp [ \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset exp] \begin_inset Quotes cld \end_inset .. \begin_inset Quotes crd \end_inset [exp] \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter [ \emph on e1 \emph default ..] \family default equivale a \family typewriter enumFrom \emph on e1 \family default \emph default , \family typewriter [ \emph on e1 \emph default , \emph on e2 \emph default ..] \family default a \family typewriter enumFromThen \emph on e1 e2 \family default \emph default , \family typewriter [ \emph on e1 \emph default .. \emph on e3 \emph default ] \family default a \family typewriter enumFromTo \emph on e1 e3 \family default \emph default y \family typewriter [ \emph on e1 \emph default , \emph on e2 \emph default .. \emph on e3 \emph default ] \family default a \family typewriter enumFromThenTo \emph on e1 e2 e3 \family default \emph default . \end_layout \begin_layout Standard Para expresiones de tipo \family typewriter Int \family default , \family typewriter [ \emph on x \emph default , \emph on y \emph default ..] \family default es la secuencia aritmética infinita cuyos dos primeros elementos son \family typewriter \emph on x \family default \emph default e \family typewriter \emph on y \family default \emph default ; \family typewriter [ \emph on x \emph default ..] \family default equivale a \family typewriter [ \emph on x \emph default , \emph on x \emph default +1,..] \family default ; \family typewriter [ \emph on x \emph default , \emph on y \emph default .. \emph on z \emph default ] \family default es como \family typewriter [ \emph on x \emph default , \emph on y \emph default ..] \family default pero termina cuando se sobrepasa \family typewriter \emph on z \family default \emph default , de modo que si \begin_inset Formula $\text{\emph{\texttt{x}}}\leq\text{\emph{\texttt{y}}}$ \end_inset la secuencia para en el primer elemento mayor a \family typewriter \emph on z \family default \emph default sin incluirlo, y si \begin_inset Formula $\text{\emph{\texttt{x}}}>\text{\emph{\texttt{y}}}$ \end_inset la secuencia para en el primero menor que \family typewriter \emph on z \family default \emph default sin incluirlo, y \family typewriter [ \emph on x \emph default .. \emph on z \emph default ] \family default equivale a \family typewriter [ \emph on x \emph default , \emph on x \emph default +1.. \emph on z \emph default ] \family default . \end_layout \begin_layout Standard Una \series bold lista por comprehensión \series default se define como \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout aexp /= \begin_inset Quotes cld \end_inset [ \begin_inset Quotes cld \end_inset exp \begin_inset Quotes cld \end_inset | \begin_inset Quotes crd \end_inset qual *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset qual) \begin_inset Quotes cld \end_inset ] \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout qual = pat \begin_inset Quotes cld \end_inset <- \begin_inset Quotes crd \end_inset exp | exp \end_layout \end_inset \end_layout \begin_layout Standard El resultado es una lista de elementos del tipo de \family typewriter exp \family default . Un \series bold cualificador \series default ( \family typewriter qual \family default ) del primer tipo es un \series bold generador \series default y uno del segundo es un \series bold filtro \series default o \series bold guarda \series default . Si \family typewriter \emph on e \family default \emph default y \family typewriter \emph on f \family default \emph default son expresiones, \family typewriter \emph on p \family default \emph default un patrón y \family typewriter \emph on Q \family default \emph default una lista de cualificadores, \family typewriter [ \emph on e \emph default | \emph on p \emph default <- \emph on f \emph default , \emph on Q \emph default ] \family default evalúa, para cada elemento de la lista \family typewriter \emph on f \family default \emph default que encaje con \family typewriter \emph on p \family default \emph default , \family typewriter [ \emph on e \emph default | \emph on Q \emph default ] \family default , en un entorno extendido por los vínculos del encaje, y concatena los resultado s, y \family typewriter [ \emph on e \emph default | \emph on f \emph default , \emph on Q \emph default ] \family default devuelve \family typewriter [ \emph on e \emph default | \emph on Q \emph default ] \family default si el booleano \family typewriter \emph on f \family default \emph default es \family typewriter True \family default o \family typewriter [] \family default en otro caso. Si \family typewriter \emph on Q \family default \emph default es vacío se entiende que \family typewriter [ \emph on e \emph default | \emph on Q \emph default ] \family default vale \family typewriter [ \emph on e \emph default ] \family default . \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout lexp /= \begin_inset Quotes cld \end_inset do \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset stmts \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout stmts = *stmt exp [ \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset ] \end_layout \begin_layout Plain Layout stmt = (exp / pat \begin_inset Quotes cld \end_inset <- \begin_inset Quotes crd \end_inset exp /) \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter do { \emph on exp \emph default } \family default equivale a \family typewriter \emph on exp \family default \emph default , que debe tener tipo \family typewriter m a \family default para algún \family typewriter m \family default de clase \family typewriter Monad \family default y algún \family typewriter a \family default ; \family typewriter do { \emph on exp \emph default ; \emph on rest \emph default } \family default equivale a \family typewriter \emph on exp \emph default >> \begin_inset space ~ \end_inset do { \emph on rest \emph default } \family default , y \family typewriter do { \emph on pat \emph default <- \emph on exp \emph default ; \emph on rest \emph default } \family default equivale a \family typewriter \emph on exp \emph default >>= \backslash \emph on pat \emph default -> \begin_inset space ~ \end_inset do { \emph on rest \emph default } \family default . \end_layout \begin_layout Section Definiciones \end_layout \begin_layout Standard Una \series bold definición \series default añade un vínculo al contexto en que se encuentra, en principio el contexto global. Está formada por una \series bold asignación de tipo \series default opcional, que indica el tipo de la variable, y una serie de ecuaciones. La asignación del tipo debe corresponder o al tipo inferido o a una restricción. No se puede dar más de una asignación a la misma variable y, si se asigna un tipo más restringido, no se puede usar la variable como si tuviera el tipo más general. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout decl = gendecl / (funlhs / pat) rhs \end_layout \begin_layout Plain Layout cdecl = gendecl / (funlhs / var) rhs \end_layout \begin_layout Plain Layout idecl = (funlhs / var) rhs / \end_layout \begin_layout Plain Layout gendecl = vars \begin_inset Quotes cld \end_inset :: \begin_inset Quotes crd \end_inset type / fixity [integer] ops \end_layout \begin_layout Plain Layout ops = op *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset op) \end_layout \begin_layout Plain Layout fixity = \begin_inset Quotes cld \end_inset infixl \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset infixr \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset infix \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{samepage} \end_layout \end_inset Las funciones se definen con una serie de \series bold ecuaciones \series default de la forma \family typewriter funlhs rhs \family default : \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout funlhs = var 1*apat / pat varop pat \end_layout \begin_layout Plain Layout rhs = ( \begin_inset Quotes cld \end_inset = \begin_inset Quotes crd \end_inset exp / 1*gdrhs) [ \begin_inset Quotes cld \end_inset where \begin_inset Quotes crd \end_inset decls] \end_layout \begin_layout Plain Layout gdrhs = guards \begin_inset Quotes cld \end_inset = \begin_inset Quotes crd \end_inset exp \end_layout \end_inset \begin_inset ERT status open \begin_layout Plain Layout \backslash end{samepage} \end_layout \end_inset \end_layout \begin_layout Standard La \series bold aridad \series default de una ecuación es el número de parámetros (número de \family typewriter apat \family default en la primera sintaxis o 2 en la segunda), y todas las ecuaciones para la misma función \family typewriter var \family default tienen la misma aridad. La función se define currificada, y para evaluarla sobre ciertos argumentos, se selecciona una \series bold cláusula \series default ( \family typewriter gdrhs \family default ) de la misma forma que se seleccionaban los \family typewriter gdpat \family default en una expresión \family typewriter case \family default , usando ecuaciones en vez de \family typewriter alt \family default s y encajando tantos argumentos como sea la aridad, y se ejecuta la expresión correspondiente. Una ecuación \family typewriter \emph on var apat \family default \emph default ... \family typewriter = \emph on exp \family default \emph default equivale a \family typewriter \emph on var apat \family default \emph default ... \family typewriter | True = \emph on exp \family default \emph default . La inferencia de tipos funciona como si la función se hubiera definido mediante una abstracción con dentro un \family typewriter case \family default . \end_layout \begin_layout Standard Las declaraciones de la forma \family typewriter pat rhs \family default definen variables globales añadiendo al contexto global los vínculos establecid os al encajar el \family typewriter rhs \family default con el patrón, y es un error si no hay encaje. Generalmente \family typewriter pat \family default es una variable. \end_layout \begin_layout Standard El segundo tipo de \family typewriter gendecl \family default establece que los operadores indicados tengan precedencia dada por el entero opcional y asociatividad por la izquierda ( \family typewriter infixl \family default ), por la derecha ( \family typewriter infixr \family default ) o ninguna ( \family typewriter infix \family default ). \end_layout \begin_layout Section Módulos \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout module /= \begin_inset Quotes cld \end_inset module \begin_inset Quotes crd \end_inset qconid [exports] \begin_inset Quotes cld \end_inset where \begin_inset Quotes crd \end_inset body \end_layout \begin_layout Plain Layout exports = \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [export *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset export) [ \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset ] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout export = qvar / qconid [ \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset .. \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [cname *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset cname)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset ] \end_layout \begin_layout Plain Layout / qconid [ \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset .. \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [qvar *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset qvar)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset ] \end_layout \begin_layout Plain Layout / \begin_inset Quotes cld \end_inset module \begin_inset Quotes crd \end_inset qconid \end_layout \begin_layout Plain Layout cname = var / con \end_layout \end_inset \end_layout \begin_layout Standard Haskell organiza los elementos en módulos, uno por fichero, cada uno con un nombre único y un contexto global formado por los vínculos establecidos en el módulo y los que se importan de otros. \end_layout \begin_layout Standard Una \series bold entidad \series default es un vínculo importado o exportado por un módulo, con un nombre (que no incluye el nombre del módulo) y un valor. \end_layout \begin_layout Standard Se exportan las entidades indicadas por \family typewriter exports \family default : \family typewriter \emph on qvar \family default \emph default para una variable, \family typewriter \emph on qconid \family default \emph default para un tipo o clase, \family typewriter \emph on qconid \emph default (..) \family default para el tipo y todos sus constructores o la clase y todos sus métodos; \family typewriter \emph on qconid \emph default ( \emph on cname \emph default , \family default ... \family typewriter ) \family default para el tipo y los constructores indicados, y \family typewriter \emph on qconid \emph default ( \emph on qvar \emph default , \family default ... \family typewriter ) \family default para el tipo y los métodos indicados. Si no hay un \family typewriter exports \family default , se exportan todos los vínculos definidos en el módulo. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout body /= \begin_inset Quotes cld \end_inset { \begin_inset Quotes cld \end_inset impdecls [ \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset topdecls] \begin_inset Quotes cld \end_inset } \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout impdecls = impdecl *( \begin_inset Quotes cld \end_inset ; \begin_inset Quotes crd \end_inset impdecl) \end_layout \begin_layout Plain Layout impdecl = \begin_inset Quotes cld \end_inset import \begin_inset Quotes crd \end_inset [ \begin_inset Quotes cld \end_inset qualified \begin_inset Quotes crd \end_inset ] qconid [ \begin_inset Quotes cld \end_inset as \begin_inset Quotes crd \end_inset qconid] [impspec] \end_layout \begin_layout Plain Layout impspec = [ \begin_inset Quotes cld \end_inset hiding \begin_inset Quotes crd \end_inset ] \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [import *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset import)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout import = var / qconid[ \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset .. \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [cname *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset cname)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \begin_layout Plain Layout / qconid[ \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset \begin_inset Quotes cld \end_inset .. \begin_inset Quotes crd \end_inset \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset / \begin_inset Quotes cld \end_inset ( \begin_inset Quotes cld \end_inset [var *( \begin_inset Quotes cld \end_inset , \begin_inset Quotes crd \end_inset var)] \begin_inset Quotes cld \end_inset ) \begin_inset Quotes crd \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Una \family typewriter impdecl \family default importa entidades del módulo \family typewriter qconid \family default , por defecto todas las que este importa, pero \family typewriter impspec \family default permite importar sólo los vínculos de los \family typewriter import \family default , con la misma semántica que los \family typewriter export \family default , o sólo los que no están en los \family typewriter import \family default si se indica \family typewriter hiding \family default . Añadir \family typewriter qualified \family default hace que las entidades se importen con nombre \family typewriter \emph on módulo \emph default . \emph on entidad \family default \emph default , donde el \family typewriter \emph on módulo \family default \emph default es el nombre del módulo del que se importa o el que se indica detrás de \family typewriter as \family default si este aparece. \end_layout \begin_layout Standard Algunos programadores prefieren usar \family typewriter qualified \family default en todos los \family typewriter import \family default , haciendo explícito el origen de cada nombre y usando \family typewriter as \family default si hace falta para acortar el nombre, mientras que otros prefieren nombres cortos y usan \family typewriter qualified \family default o \family typewriter hiding \family default según sea necesario para evitar conflictos de nombres. \end_layout \begin_layout Standard Los módulos permiten crear tipos de datos abstractos, pues exportar un tipo sin constructores hace que este solo se pueda usar fuera del módulo a través de las operaciones exportadas, permitiendo cambiar la representación del tipo sin afectar a sus usuarios. \end_layout \begin_layout Standard Haskell no especifica una relación entre nombres de módulo y de fichero, pero GHC busca el módulo \family typewriter \emph on A1 \emph default . \family default ... \family typewriter . \emph on An \family default \emph default en \family typewriter \emph on A1 \emph default / \family default ... \family typewriter / \emph on An \emph default .hs \family default en el directorio raíz del programa (el directorio actual si se usa GHCi) y una serie de directorios predefinidos. \end_layout \begin_layout Standard Un \series bold preludio \series default es un módulo que se importa por defecto en los demás como si hubiera un \family typewriter import \emph on Preludio \family default \emph default , salvo que haya un \family typewriter impdecl \family default explícito para ese preludio. El único es \family typewriter \lang english Prelude \family default \lang spanish , con \series bold operaciones primitivas \series default incluidas en el evaluador, como las operaciones aritméticas básicas, y tipos y funciones de utilidad. \end_layout \end_body \end_document