Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Pablo Speciale
NDICE G ENERAL
NDICE G ENERAL
17
17
4.4. Caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
1.1. Valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
1.2. Expresiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
1.3. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
4.8. Enumeraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
4.9. Tuplas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
1.6. Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.10. Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
ndice
1. Conceptos Importantes
2. Sintaxis de Haskell
5. Ms sobre funciones
24
24
2.2. Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Currificacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
27
2.4. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
2.4.1. Identificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
2.4.2. Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
10
2.5. Secciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
11
11
13
3.1. Prelude.hs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
13
14
14
4. Tipos de Haskell
4.1. Booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
16
6. Evaluacin
29
6.1. Reduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
31
1.4. E CUACIONES
1.
ORIENTADAS
Conceptos Importantes
1. C ONCEPTOS I MPORTANTES
En esta seccin se explica que es un lenguaje funcional puro. Adems, se dan algunas definiciones
que son la esencia de Haskell.
Expresion a def inir = Expresion def inida
1.1.
e1 = e2
Valores
Entidades matemticas abstractas con ciertas propiedades. Una expresin denota un valor. Entre las
clases de valores que una expresin puede denotar, se incluyen: nmeros de varios tipos (Int, Integer,
Float, etc.), caracteres, funciones y listas. Observar que, en Haskell, las funciones tambin son valores.
1.2.
Visin denotacional: se define que el valor denotado por e1 es el mismo que el denotado por e2 .
Visin operacional: para calcular el valor de una expresin que contiene a e1 , se puede reemplazar
e1 por e2 .
Expresiones
Nota
Dada una expresin bien formada, determinamos el valor que denota mediante ecuaciones. Y calculamos el valor de la misma, reemplazando subexpresiones, de acuerdo con las reglas dadas por las
ecuaciones, a sto se lo llama reduccin (ver seccin 6).
Expresiones compuestas: se arman combinado subexpresiones. Por abuso de notacin, slo les
decimos expresiones.
Notas
1. No confundir entre valores y su representacin (mediante expresiones). Pueden existir muchas formas de representar un mismo valor. Por ejemplo, 5 101 (en binario) V (en nmeros Romanos).
2. Una expresin est bien formada si cumple con las reglas sintcticas y reglas de asignacin de
tipo.
3. Algunos valores no tienen representacin cannica, por ejemplo, los valores funcionales.
1.3.
Funciones
Visin denotacional: una funcin es un valor matemtico que relaciona cada elemento de un conjunto (de partida) con un nico elemento de otro conjunto (de llegada).
Visin operacional: una funcin es un mecanismo que dado un elemento del conjunto de partida,
calcula el elemento correspondiente del conjunto de llegada.
Transparencia Referencial: el valor de una expresin depende slo de los elementos que la constituyen.
Una definicin ms informal, cuando dos cosas son iguales que sean iguales en todas partes. Por ejemplo,
en C, uno puede hacer lo siguiente:
x = x + 1;
Se le asigna a x el valor de x+1. Este ejemplo muestra un lenguaje que no posee la importante propiedad
de Transparencia Referencial, pues x no vale lo mismo antes y despus de la asignacin. Un lenguaje
as se dice que posee Efectos colaterales.
La Transparencia Referencial implica:
Abstraccin de detalles de ejecucin.
Posibilidad de demostrar propiedades usando las propiedades de las subexpresiones y mtodos de
deduccin lgicos.
Extensionalidad
Este principio recibe el nombre de principio de extensionalidad.
f =g
fx=gx
Lenguaje funcional puro: lenguaje de expresiones con transparencia referencial y funciones de alto orden, cuyo modelo de cmputo es la reduccin realizada mediante el reemplazo de igualdad por igualdad.
Haskell es un lenguaje funcional puro.
1.6. T IPOS
1.6.
DE
H ASKELL
2. Sintaxis de Haskell
Tipos
Conjunto de valores con propiedades comunes. Los tipos denotan conjuntos de valores.
Tipado Fuerte (strong typing): toda expresin debe tener un tipo para ser vlida.
Notacin:
2. S INTAXIS
e :: A
se lee
La sintaxis de Haskell diferencia entre maysculas y minsculas. Se dice que es Case sensitive.
2.2. Comentarios
Inferencia de tipos:
Dada un expresin e, determinar si tiene tipo o no segn las reglas, y cul es ese tipo
1.
Chequeo de tipos:
si
m, n :: Int
si
d = e y e :: A
(e1 , e2 ) :: (A, B)
m + n :: Int
d :: A
(e, A) Bool
nombre_variable :: Tipo
nombre_variable = expresion
como en el ejemplo
size :: Integer
size = 12 + 13
2.4. Funciones
Existen dos formas de nombrar una funcin, mediante un identificador (por ejemplo, sum, product
y fact), o mediante un smbolo de operador (por ejemplo, * y +)
2.4.1.
Identificadores
Los identificadores de variables o funciones deben comenzar con una letra minscula, seguido, opcionalmente por una secuencia de caracteres, cada uno de los cuales es: una letra, un dgito, un apstrofe
() o un guin bajo (_). Los siguientes son ejemplos posibles de identificadores:
sum
fintSum
nombre_con_guiones
Los siguientes identificadores son palabras reservadas y no pueden utilizarse como nombres de funciones o variables:
case
of
then
else
infixr class
where
let
in
data
type
infix
instance primitive
if
infixl
2.4. F UNCIONES
2.4.2.
Operadores
2. S INTAXIS
2.4.5.
Algunas funciones se escriben entre sus (dos) argumentos en lugar de precederlos. A una funcin
escrita usando la notacin infija se le llama un operador. Por ejemplo,
3 <= 4
en lugar de
!
?
#
@
%
\
&
|
*
-
<
minimo
:: (Integer, Integer) -> Integer
minimo (x,y) | x <= y
= x
| otherwise = y
menorIgual 3 4
H ASKELL
DE
Esta forma de definicin utiliza ecuaciones con guardas. Cada clusula consiste en una condicin, o
guarda, y en una expresin separada de la guarda por un signo de igualdad (=). En general una ecuacin
con guardas toma la forma:
f x1 x2 ... xn | condicion1 = e1
| condicion2 = e2
.
.
.
| condicionm = em
Se proporcionan dos mecanismos simples para utilizar un identificador como un smbolo de operador
o un smbolo de operador como un identificador:
Cualquier identificador ser tratado como un smbolo de operador si est encerrado entre comillas
inversas (). Por ejemplo,
x mod y
es equivalente a
mod x y
Cualquier smbolo de operador puede ser tratado como un identificador encerrndolo en parntesis.
Por ejemplo,
x + y
2.4.4.
es equivalente a
Definiciones recursivas
(+) x y
fact
:: Integer -> Integer
fact n = if n==0 then 1 else
n * fact(n-1)
La declaracin de una funcin f est formada por un conjunto de ecuaciones con el formato:
Otro modo de escribir la misma funcin pero con ajuste de patrones (Pattern Matching).
fact
:: Integer -> Integer
fact
0
= 1
fact (n+1) = (n+1) * fact n
Observar que se us 0 y n+1 para que los patrones sean disjuntos. Al a ser los patrones disjuntos, el
orden en que aparecen las ecuaciones no importa; en caso contrario, s es importante el orden.
Leer seccin 1.5.1 del libro.
No es del todo cierto que una funcin tome n argumentos, como se ver en la seccin Currificacin.
2.4.7.
Definiciones locales
Considrese la siguiente funcin que calcula el nmero de races diferentes de una ecuacin cuadrtica de la forma a x2 + b x + c = 0
numeroDeRaices :: Int -> Int -> Int -> Int
numeroDeRaices a b c
10
2.5. S ECCIONES
2. S INTAXIS
DE
H ASKELL
11
2.5. Secciones
| discr > 0
= 2
| discr == 0
= 1
| discr < 0
= 0
where discr = b*b - 4*a*c
Las definiciones locales pueden tambin ser introducidas por let de la forma:
Una excepcin: (x) se interpreta como la aplicacin del operador unario de negacin.
Leer seccin 1.4.4 del libro.
Expresiones case
Una expresin case puede ser utilizada para evaluar una expresin y, dependiendo del resultado,
devolver uno de los posibles valores.
paridad :: Int -> String
paridad x = case (x mod 2) of
0 -> "par"
1 -> "impar"
2.4.9.
Aplicacin de Funciones
Notar que en la aplicacin de una funcin, los argumentos no necesitan ser encerrados entre parntesis
(cmo usualmente se hace en matemticas). Supngase la siguientes
9
9
8
7
7
6
5
5
4
4
3
2
!!
.
^
*
/,
div,
rem,
+,
\\
++,
:
==,
/=,
<,
<=,
elem,
notElem
&&
||
mod
>=,
>
Observaciones
La aplicacin de funciones tiene la mayor precedencia.
ABC
Por ejemplo, si queremos calcular el promedio entre 5 y 47, podemos hacer en hugs (ver seccin 3):
Hugs> promedio 5 47
26.0
significa
A (B C)
Los parntesis van a ser necesarios cuando queramos romper el orden de precedencia estndar de los
operadores. Como la aplicacin de funcin tiene precedencia ms alta que todos los dems operadores,
si queremos calcular el promedio ente 6 y 9+9, tenemos que hacer
Hugs> promedio 6 (9+9)
12.0
Cmo es posible evitar la utilizacin de separadores que marquen el final de una ecuacin, una
declaracin, etc. Por ejemplo, dada la siguiente expresin:
ejemplo x y z = a + b
where a = f x y
b = g z
Cmo sabe el sistema Haskell que no debe analizarla como:
Pues,
promedio 6 9 + 9
infixl
infixr
infixr
infixl
infix
infixl
infix
infixr
infix
infix
infixr
infixr
equivale a
(promedio 6 9) + 9
ejemplo x y z
= a + b
where a
= f x
y b = g z
12
2.7. D ISPOSICIN
DEL CDIGO
La respuesta es que el Haskell utiliza una sintaxis bidimensional denominada espaciado (layout) que
se basa esencialmente en que las declaraciones estn alineadas por columnas. En el ejemplo anterior,
obsrvese que a y b comenzaban en la misma columna. Las reglas del espaciado son bastante intuitivas
y podran resumirse en:
1. El siguiente carcter de cualquiera de las palabras clave where, let u of es el que determina la
columna de comienzo de declaraciones en las expresiones where, let o case correspondientes. Por tanto podemos comenzar las declaraciones en la misma lnea que la palabra clave, en la
siguiente o siguientes.
2. Es necesario asegurarse que la columna de comienzo dentro de una declaracin est ms a la derecha que la columna de comienzo de la siguiente clusula. En caso contrario, habra ambigedad,
ya que el final de una declaracin ocurre cuando se encuentra algo a la izquierda de la columna de
comienzo.
El espaciado es una forma sencilla de agrupamiento que puede resultar bastante til. Por ejemplo, la
declaracin anterior sera equivalente a:
ejemplo x y z = a + b
where { a = f x y ;
b = g z }
3. C OSAS
SOBRE EL
H UGS
13
3.1. Prelude.hs
El prelude es un fichero de nombre Prelude.hs que es cargado automticamente al arrancar Hugs
y contiene la definicin de un conjunto de funciones que podemos usar cuando las necesitemos. Algunos
ejemplos: div, mod, sqrt, id, fst, snd.
__ __ ____
___
|| || || || ||__
||__|| ||__|| __||
___||
Version: May 2006
_________________________________________
Hugs 98: Based on the Haskell 98 standard
Copyright (c) 1994-2005
World Wide Web: http://haskell.org/hugs
Report bugs to: hugs-bugs@haskell.org
_________________________________________
Haskell 98 mode: Restart with command line option -98 to enable extensions
Type :? for help
Hugs>
Hugs evaluar cualquier expresin, sintcticamente correcta, que se ingrese en el prompt
Hugs> <expresion>
<resultado>
Por ejemplo, si ingresemos (7 + 4) 3, la evaluar y nos devolver 33
Hugs> (7+4)*3
33
Si ingresamos sqrt 2, nos devolver una aproximacin de
Hugs> sqrt 2
1.4142135623731
14
3.4. U N
3.3.
PROGRAMA EN
H ASKELL
Comandos de Hugs
3. C OSAS
SOBRE EL
H UGS
15
A una lista de definiciones se la denomina script. Los pasos a seguir para resolver un problema seran
los siguientes:
La primer lnea dice que se puede usar como abreviatura slo la primera letra de cada comando. Observar
estos comandos equivalentes:
Hugs>
id ::
Hugs>
id ::
Hugs>
:type id
a -> a
:t id
a -> a
3.4.
Un programa en Haskell
Por ahora hemos evaluado expresiones en el prompt de Hugs y escrito algunas definiciones. Pero,
dnde guardamos esas definiciones? cmo hacemos para usarlas? En esta seccin responderemos
todas estas cuestiones.
1. Escribimos un script con la definicin de todas las funciones que necesitemos para resolver el problema. Para ello podemos utilizar cualquier editor de texto, aunque es recomendable usar alguno
que resalte automticamente la sintaxis de Haskell. Guardamos el archivo con una extensin .hs.
2. Cargamos el script en Hugs. Para ello utilizamos el comando :load seguido del nombre del archivo. Ahora en el prompt de Hugs ya podemos evaluar cualquier expresin que haga referencia a
funciones definidas en el script.
Al escribir el script debemos recordar que Haskell distingue entre maysculas y minsculas (se dice
que es Case Sensitive. Por ejemplo, mi_funcion y mi_Funcion resultan identificadores distintos.
Una buena prctica de programacin es documentar siempre el cdigo fuente. Un comentario en un
script es informacin de valor para el lector humano, ms que para el computador (no interviene para
nada al momento de evaluar una expresin). El smbolo -- inicia un comentario, que ocupa la parte
de la linea hacia la derecha del smbolo.
16
4.2. N MEROS
4.
ENTEROS
Tipos de Haskell
DE
H ASKELL
Existen dos tipos bsicos para representar enteros: Int e Integer. Ambos incluyen los enteros
negativos, el cero y los enteros positivos. La nica diferencia es que Int representa enteros de rango
acotado, mientras que Integer representa enteros de rango arbitrario.
Esto significa que operar con valores de tipo Int puede provocar un desbordamiento, y el resultado
puede no ser el correcto. En cambio, la aritmtica Integer no presenta este inconveniente. Notar que
este beneficio se gana a costo de algo de prdida de performance: la aritmtica Integer es ms lenta
que la aritmtica Int.
(+)
(*)
(-)
(^)
negate
div
rem/mod
Booleanos
Se representan por el tipo Bool y contienen dos valores: False y True. El tipo de datos Bool se
puede definir con una declaracin de tipos de datos:
data Bool
False | True
x && y
x || y
not x
x == y
x /= y
xy
xy
x
xy
x 6 y o x xor y
Haskell tambien incluye una construccin que permite seleccionar entre dos alternativas dependiendo
de un valor booleano.
if condicion then expresion1 else expresion2
funciona de la siguiente manera: se evala condicion; si reduce a True (i.e. la condicin es verdadera)
se evalua expresion1 y se devuelve su valor, y si reduce a False (i.e. la condicin es falsa), se evalua y
devuelve el valor de expresion2.
Obsrvese que una expresin de ese tipo slo es aceptable si condicion es de tipo Bool y si
expresion1 y expresion2 son del mismo tipo.
Leer seccin 2.1 del libro.
17
Se introduce algunos tipos de datos bsicos (Booleanos, Char, Int) y tipos de datos compuestos (tuplas, listas, funciones).
4.1.
4. T IPOS
odd
even
abs
signum
suma.
multiplicacin.
substraccin.
potenciacin.
menos unario (la expresin "-x" se toma como "negate x")
divisin entera
resto de la divisin entera. Siguiendo la ley:
(x div y)*y + (x rem y) == x
mdulo, como rem slo que el resultado tiene el mismo
signo que el divisor.
devuelve True si el argumento es impar
devuelve True si el argumento es par.
valor absoluto
devuelve -1, 0 o 1 si el argumento es negativo, cero
positivo, respectivamente.
Ejemplos
3^4 == 81, 7 div 3 == 2, even 23 == False
7 rem 3 == 1, -7 rem 3 == -1, 7 rem -3 == 1
18
4.4. C ARACTERES
4. T IPOS
La diferencia entre Float y Double reside en que los primeros representan nmeros en punto
flotante de precisin simple, mientras que los segundos, nmeros en punto flotante de precisin doble.
El prelude incluye tambin mltiples funciones de manipulacin de flotantes:
(+), (-), (*), (/)
(^)
(**)
sin, cos, tan
asin, acos, atan
ceiling
floor
truncate
round
fromIntegral
log
sqrt
4.4.
Caracteres
Representados por el tipo Char, los elementos de este tipo representan caracteres individuales como
los que se pueden introducir por teclado. Los valores de tipo carcter se escriben encerrando el valor
entre comillas simples, por ejemplo
Algunos caracteres especiales deben ser introducidos utilizando un cdigo de escape; cada uno de
stos comienza con el carcter de barra invertida (\) , seguido de uno o ms caracteres que seleccionan
el carcter requerido. Algunos de los ms comunes cdigos de escape son:
En contraste con algunos lenguajes comunes (como el C, por ejemplo), los valores de tipo Char son
completamente distintos de los enteros. Sin embargo, el prelude proporciona dos funciones primitivas,
ord y chr, que permiten realizar la conversin.
19
Notar que 0 y 0 son dos valores distintos. El primero es de tipo caracter y el segundo de tipo
entero.
barra invertida
comilla simple
comilla doble
salto de lnea
H ASKELL
a, 0, ., y Z
\\
\
\"
\n
DE
4.6. Listas
Si a es un tipo cualquiera, entonces [a] representa el tipo de listas cuyos elementos son valores de
tipo a. Por ejemplo,
3
20
4. T IPOS
xs :: [Int]
xs = [1, 8, 2, 4]
DE
H ASKELL
21
Convenio: para representar una lista se usa el convenio xs, para listas de listas se usa xss, y as sucesivamente.
4.8. Enumeraciones
Un modo de definir un nuevo tipo de datos es enumerar explcitamente sus valores. Por ejemplo,
data Dia = Dom | Lun | Mar | Mie | Jue | Vie | Sab
4.7.
Cadenas (String)
Una cadena es tratada como una lista de caracteres y el tipo String se toma como una abreviacin
de [Char]. El tipo String es un renombramiento:
type String = [Char]
Los nombres de las constructoras se distinguen de otras clases de nombres hacindolos comenzar por
una letra mayscula. El nombre de un tipo declarado, tambin comienza por una letra mayscula.
El tipo Dia define un conjunto de siete valores distintos. Cada uno de estos valores se dice qie es un
contructores del tipo Dia.
Por defecto, esta definicin no me permite operar con valores de tipo Dia en la manera que esperaria:
no puedo comparar dos valores por igualdad, no puedo imprimir sus valores en pantalla, etc.
Para poder hacer esto, debo agregarle a la defincin una opcin ms:
Las cadenas pueden ser escritas como secuencias de caracteres encerradas entre comillas dobles. Todos
los cdigos de escape utilizados para los caracteres, pueden utilizarse para las cadenas.
Hugs> "hola"
"hola"
Hugs> [h,o,l,a]
"hola"
Hugs>
Ord: permite usar los operadores <, <=, > y >= con valores de tipo a. La relacin < est dada
por el orden en que se enumeran los constructores en la definicin del tipo. As, Lun < Vie y
Dom < Sab,
Puesto que las cadenas son representadas como listas de caracteres, todas las funciones para listas
pueden ser utilizadas tambin con cadenas:
Enum: define las funciones fromEnum :: a -> Int y toEnum :: Int -> a. La funcin fromEnum asocia un natural a cada uno de los valores de a, de acuerdo al orden en la
declaracin y comenzando con 0. toEnum es la inversa a izquierda de fromEnum. Por ejemplo
fromEnum Dom reduce a 0, fromEnum Mie reduce a 3 y toEnum 2 == Mar4 reduce a
True.
22
4.10. P OLIMORFISMO
4. T IPOS
DE
H ASKELL
23
Entonces, la identidad es una funcin polimrfica. El tipo de su argumento puede ser instanciado. Por
ejemplo,
4.9.
(id 3)
:: Int
(id True) :: Bool
Tuplas
Un modo de combinar tipos para crear tipos nuevos es construir pares. El tipo (A,B) corresponde a
la operacin de producto cartesiano de la teora de conjuntos.
Contamos con los destructores fst y snd que devuelve la primer y segunda componente de un par
respectivamente; por ejemplo fst (2,b) reduce a 2 y snd (2,b) reduce a b.
Ms general, si T1 , T2 , ..., Tn son tipos y n 2, entonces hay un tipo de n-tuplas escrito (T1 , T2 , ..., Tn )
cuyos elementos pueden ser escritos como (x1 , x2 , ..., xn ) donde cada x1 , x2 , ..., xn tiene tipos T1 , T2 , ..., Tn
respectivamente.
Ejemplo
(1, [2], 3)
:: (Int, [Int], Int)
(a, False) :: (Char, Bool)
((1,2),(3,4)) :: ((Int, Int), (Int, Int))
Obsrvese que, a diferencia de las listas, los elementos de una tupla pueden tener tipos diferentes. Sin
embargo, el tamao de una tupla es fijo.
Por completitud, Haskell tambin proporciona una tupla vaca. Por definicin, la expresin (), leda
unit, tiene tipo (). El tipo () tiene dos elementos, y (). Un uso posible de () es convertir las constantes
en funciones; por ejemplo,
pifun
pifun
:: () -> Float
= 3.14159
Al elevar las constantes al nivel de las funciones, se puede ir ms all en el estilo de programacin no
aplicativo. Por ejemplo, se podra escribir
cuadrado . cuadrado . pifun
en lugar de
(cuadrado . cuadrado) pi
4.10. Polimorfismo
Algunas funciones y operadores trabajan con muchos tipos. Por ejemplo,
id :: a -> a
id x = x
Se lee id es una funcin que dado un elemento de algn tipo a, retorna un elemento de ese mismo tipo.
Aqu a denota variables de tipo. Un tipo que contenga variables de tipo se denomina tipo polimrfico.
y aqu
y aqu
24
5.2. C URRIFICACIN
5.
Ms sobre funciones
25
SOBRE FUNCIONES
5.1.
5. M S
Una expresin que denota una funcin son las lambda abstracciones:
(\y -> y + 1)
x . x+x
var . expresion
El significado es el siguiente:
(\ x E) x0 E [x := x0 ]
Por ejemplo,
succ = \y -> y + 1
Y la expresin anterior queda
(\x -> x + x)
(\y -> y + 1)
< Por regla anterior >
(x + x) [ x := 2 ]
=
2 + 2
5.2.
=
=
x+x
\xx+x
Currificacin
Un artificio til para reducir el nmero de parntesis de una expresin consiste en reemplazar un argumento estructurado por una secuencia de argumentos ms simples. Para ilustrar esta idea, consideremos
la funcin suma.
suma :: (Integer,Integer) -> Integer
suma (x,y) = x + y
=
=
=
=
=
12 89
def. de lambda expresiones >
:= 12]
Sustitucin >
def. de lambda expresiones >
Sustitucin >
Aritmtica >
26
5.2. C URRIFICACIN
Observe aqu que la funcin annima se comporta como lo hara sumac. Veamos qu es lo que sucede:
sumac
sumac x
sumac x y
=
=
=
\ x (\ y x + y)
\y x+y
x+y
Para que la currificacin funcione de un modo consistente, necesitamos que la operacin de aplicacin
funcional asocie a la izquierda en las expresiones. As,
sumac x y
cuadrado cuadrado x
significa
significa
(suma x) y
(cuadrado cuadrado) x
Observar que la ltima es incorrecta. Tambin observar que el operador asocia a la derecha. Esto es:
ABC
significa
A (B C)
5. M S
27
SOBRE FUNCIONES
La funcin uncurry hace lo opuesto y convierte una funcin currificada en otra que no lo es.
uncurry :: (a -> b -> c) -> (a,b) -> c
uncurry f (x,y) = f x y
Leer seccin 1.4.2 del libro.
5.2.1.
Para fines prctico, slo es necesario pensar que la funciones toman una secuencia de argumentos y
devuelve un resultado. Por ejemplo,
suma4 :: Int -> Int -> Int -> Int -> Int
suma4 x1 x2 x3 x4 = x1 + x2 + x3 + x4
Aunque nos quedamos con sta idea intuitiva de currificacin, es didctico ver cmo queda poniendo
todos los parntesis.
suma4 :: Int -> (Int -> (Int -> (Int -> Int)))
(((suma4 x1) x2) x3) x4 = x1 + x2 + x3 + x4
Nos quedamos con la primera definicin de suma4.
suma 1 = succ
Instanciando el x a 1
sumac 1
=
Recordar la Relacin entre identificadores y operadores (ver 2.4.3). Por dicha relacin, una definicin alternativa sera,
\y -> 1 + y
=
Si lo deseamos, siempre podemos convertir una funcin no currificada en otra currificada. La funcin
curry toma un funcin no currificada y devuelve un versin currificada de la misma funcin; su definicin
es
curry :: ((a,b) -> c) -> a -> b -> c
curry f x y = f (x,y)
(f . g) . h
f . (g . h)
para todas las funciones f, g y h de tipos apropiados. En consecuencia, no hay necesidad de poner
parntesis al escribir secuencias de composiciones.
Leer seccin 1.4.7 del libro.
28
5.4. F UNCIONES
5.4.
TOTALES Y PARCIALES .
Decimos que una funcin es total, si est definida para todo elemento de su dominio. En otras palabras, f :: A -> B es total si y slo si f x 6= para todo x::A. En caso contrario, decimos que
f es parcial. Ver la definicin de Botton () en la seccin 6.1.
6. E VALUACIN
29
6. Evaluacin
6.1. Reduccin
Definicin: cero o ms contracciones (reemplazo de un redex).
Redex (reducible expresin): subexpresin que coincide con una instancia del lado izquierdo de un
ecuacin. Un redex ms interno es aquel que no contiene otro redex. Un redex ms externo es aquel que
no est contenido en otro redex. Otra definicin posible, subexpresin que se puede reemplazar por otra.
Forma normal: expresin que no contiene redexes (o sea, expresin que no se puede reducir). No toda
expresin tiene forma normal. La reduccin pretende obtener la formal normal.
double resulta una funcin total, mientras que fact y reciproco resultan parciales. Esto se
debe a que fact aplicado a un entero negativo denota una computacin que no termina, y reciproco
no est definido en cero.
Notar que en programacin funcional tenemos una definicin diferente de dominio de una funcin a
la que tenemos usualmente en matemticas. En matemticas escribimos f : A B para denotar que f
es una funcin definida para todo x en A, mientras que en Haskell, f :: A -> B significa que f est
definida (i.e. no evala a ) para eventualmente alguno de los valores en A.
Visin denotacional:
Botton (): valor terico que representa a un error o a una computacin que no termina.
Visin operacional:
expresin cuyas computaciones no terminan (infinitos).
expresin que no estn definidas (1/0).
Notas
No se puede manejar de manera operacional.
No se puede preguntar si algo es sin obtener . Comparacin con da .
Funcin estricta:
f=
f=
6
30
6.2. E VALUACIN
PEREZOSA ( O
Lazy)
Propiedad 1. La reduccin ms externa tiene la propiedad importante de que si una expresin tiene
forma normal, entonces sta la encontrar.
6. E VALUACIN
31
=
=
=
=
.
.
.
fst
fst
fst
fst
(2,
(2,
(2,
(2,
infinito
infinito
infinito
infinito
+
+
+
+
1)
1 + 1)
1 + 1 + 1)
1 + 1 + 1 + 1)
Propiedad 2.
Orden aplicativo
Orden normal
Un argumento no es necesariamente evaluado por completo; slo se evalan aquellas partes que
constituyen efectivamente al cmputo.
Si un argumento se evala, tal evaluacin se realiza slo una vez.
Ventajas
2
TODAS las funciones son estrictas
hay funciones estrictas y no estrictas
Nota: la reduccin ms externa a veces puede necesitar ms pasos que la reduccin ms interna. El
problema surge con cualquier funcin cuya definicin contenga apariciones repetidas de un argumento.
Por ejemplo, el resultado de evaluar en orden aplicativo la siguiente expresin:
Obsrvese que se necesit un paso ms porque en la definicin de cuadrado aparece repetido su argumento. Esto es:
cuadrado x = x * x
Desventajas
Adoptaremos la evaluacin lazy como nuestro modelo de clculo porque tiene las propiedades deseables anteriormente mencionadas.
Leer seccin 7.1 del libro.
7 * 7
=
cuadrado (3 + 4)
=