Está en la página 1de 6

Pre-Introducci on a la Programaci on Funcional en Haskell

Paradigmas de Lenguajes de Programaci on 20 cuatrimestre 2007

1.

Expresiones, valores y tipos

Le ejecuci on de un programa en Haskell se realiza a trav es de la evaluaci on de expresiones (t erminos sint acticos) que denotan valores (entidades abstractas que entendemos como respuestas). Ejemplos de expresiones son
a 3+4 (5 > 0, 9)

cuyos valores asociados son la letra a, el n umero 7 y el par ordenado cuya primera componente es el valor verdadero y al segunda el n umero 9. As como podemos asociar las entidades reales o matem aticas con un conjunto, las expresiones en Haskell tienen asociado un tipo. El s mbolo :: sirve para indicar expl citamente el tipo de las expresiones.
a :: Char 3 + 4 :: Integer (5 > 0, 9) :: (Bool, Integer)

El lenguaje tiene un conjunto de tipos predenidos, de los cuales ya mencionamos algunos: Tipos simples como Integer, Double, Char, Bool, etc. Tuplas de cualquier longitud. Por ejemplo, (2 5 + 1, 4 >0, 22.1) es de tipo (Integer, Bool, Double).

1.1.

Funciones

Una de las formas m as interesantes de expresiones es la funci on, cuyo tipo esta indicado por una echa: a b es el tipo de las funciones que reciben un argumento de tipo a y devuelven un argumento de tipo b. Las funciones en Haskell son expresiones como cualquier otra: pueden ser argumento de otras funciones, devolverse como resultado, contenerse en estructuras de datos, etc. 1

Las sintaxis principal para denir funciones es muy parecida a la notaci on matem atica: a trav es de ecuaciones. La aplicaci on de una funci on a un valor f (x) se escribe f x. Por ejemplo, podemos denir la funci on sucesor de la siguiente forma:
sucesor n = n + 1

es decir con una ecuaci on que indica que el sucesor de n es n + 1 para cualquier n. Los operadores tambi en son funciones, con notaci on inja. En el mundo matem atico la denici on de una funci on no siempre se corresponde con una u nica ecuaci on, sino que puede estar separada en casos: signo : R Z 1 si x < 0 0 si x = 0 signo (x) = 1 si x > 0 En Haskell, usamos guardas, que escribimos con el s mbolo | : una ecuaci on de la forma f x | cond =resultado signica que la funci on eval ua a su resultado s olo si se cumple cond:
signo :: Double Integer signo x | x < 0 = -1 | x= =0 =0 | x>0 =1

Las funciones tambi en se pueden denir caso por caso:


siguienteVocal siguienteVocal siguienteVocal ... siguienteVocal etc. :: Char Char a = e b = e j = o

Ya sea usando guardas o deniendo casos individuales, una funci on puede denirse a trav es de m as de una ecuaci on. En ese caso, si evaluamos la funci on con un argumento determinado, a este no necesariamente le corresponda una u nica ecuaci on: puede corresponderle m as de una, en cuyo caso la que se eval ua es la primera, y puede suceder que no le corresponda ninguna, en cuyo caso (igual que en matem atica) decimos que la funci on esta indenida en ese argumento. A las funciones denidas en todos sus argumentos las llamamos totales, y a las que se indenen para alg un argumento, parciales. ejemplo 1: Programemos la siguiente funci on: acotarAUnDigito : Z Z si n > 9 9 9 si n < 9 acotarAUnDigito (n) = n en cualquier otro caso Podemos usar guardas para separar los distintos casos: 2

acotarAUnDigito :: Integer Integer acotarAUnDigito n | n > 9 = 9 | n < -9 = -9 | n 9 && n -9 = n

Ac a las tres condiciones de las guardas son disjuntas, pero la de la u ltima ecuaci on es un poco m as complicada. Una opci on podr a ser aprovechar el orden de evaluaci on: la u nica forma de evaluar la u ltima ecuaci on es que no se cumpla ninguna de las condiciones anteriores, y si eso sucede, tenemos que evaluarla para cualquier n. Podemos entonces reemplazar la u ltima condici on por True, que en ese lugar de la denici on, tiene el efecto cualquier otro caso que buscamos:
acotarAUnDigito n | n > 9 = 9 | n < -9 = -9 | True = n

Haskell tiene predenida la palabra otherwise como sin onimo de True para una lectura m as natural de la denici on.
acotarAUnDigito n | n > 9 = 9 | n < -9 = -9 | otherwise = n

1.1.1.

Recursi on

Recordemos la denici on (matem atica) de la funci on factorial : factorial : N N factorial (0) = 1 factorial (n) = n factorial (n 1)

si n > 0

Podemos denir esta funci on en Haskell con una correspondencia directa:


factorial :: Integer Integer factorial 0 = 1 factorial n | n > 0 = n factorial (n-1)

Esta funci on es recursiva porque su evaluaci on (en ciertos argumentos) involucra el llamado a la misma funci on que se esta deniendo. La recursi on es una herramienta poderosa y usada muy frecuentemente en los programas en Haskell. 1.1.2. Curricaci on

Tambi en como en matem atica, las funciones pueden tener m as de un argumento:

potencia : N R R potencia (0, x) = 1 potencia (n, x) = x potencia (n 1, x)

si n > 0

En Haskell, podemos usar tuplas para contener los argumentos necesarios. En general, cuando una variable no aparece del lado derecho de una ecuaci on, puede reemplazarse por un gui on bajo (_).
potencia :: (Integer, Double) Double potencia (0, _) = 1 potencia (n, x) | n > 0 = x potencia (n - 1, x)

Otra forma de denirla es a trav es de la misma funci on curricada : una funci on equivalente de un u nico argumento, que devuelve una funci on que completa el trabajo:
potencia :: Integer Double Double potencia 0 _ = 1 potencia n x | n > 0 = x potencia (n - 1) x

Ac a, potencia es una funci on que recibe un entero n y devuelve la funci on potencia n; esta funci on recibe a su vez un n umero x y devuelve el resultado de elevar x a la n. La curricaci on es una correspondencia entre las funciones del primer estilo (argumentos en una tupla) y el segundo (argumentos yuxtapuestos). Esta correspondencia siempre existe, y nos permite la denici on de funciones a trav es de la aplicaci on parcial. Se podr a denir por ejemplo:
cuadrado, cubo, potCuarta :: Double Double cuadrado = potencia 2 cubo = potencia 3 potCuarta = potencia 4

y luego usarlas para computar cuadrados, cubos, etc.

1.2.

Listas

Otra familia de tipos predenidos en el lenguaje es el de las listas: secuencias ordenadas de elementos de un mismo tipo, con repeticiones. [Integer] representa el tipo lista de enteros, [Bool] es una lista de booleanos, etc. Las expresiones de tipo lista se construyen con [] (que representa la lista vac a) y : (a:as es la lista que empieza con el elemento a y sigue con la lista as). Tambi en pueden escribirse entre corchetes, con los elementos separados por comas:
[] :: [Bool] [3] :: [Integer] a : (b : (c : [])) :: [Char] [2 > 0, False, a = = b] :: [Bool] [[], [1], [1,2]] :: [[Integer]]

El tipo String es sin onimo de [Char], y las listas de este tipo se pueden escribir entre comillas: "plp" es lo mismo que [p, l, p].

2.

Deniendo nuevas expresiones y tipos

Haskell tambi en permite denir nuevos tipos, con la clausula data. Denimos un nuevo tipo dando su nombre y describiendo la forma que tienen los valores de ese tipo.
data Dia = Lun | Mar | Mie | Jue | Vie | Sab | Dom

Esta denici on dice que un valor de tipo Dia consiste de uno de siete posibles constructores, todos ellos sin argumentos.
data FormaGeometrica = Circulo Double | Rectangulo Double Double

Los valores de tipo FormaGeometrica son de la forma Circulo x o bien Rectangulo x y, donde n y m son n umeros. En este caso los constructores del tipo reciben argumentos, que por ejemplo pueden representar el radio del c rculo y la base y altura del rect angulo respectivamente.
data BinTree a = Nil | Branch a (BinTree a) (BinTree a)

Esta denici on dice que, para cualquier tipo a, los valores BinTree a son o bien Nil o Branch x t1 t2 donde x es de tipo a y t1 y t2 son a su vez de tipo BinTree a. Este es un tipo param etrico, pues su denici on incluye variables de tipo, y es tambi en recursivo, porque algunos de los constructores tienen argumentos del tipo que se esta deniendo. Las funciones sobre tipos construidos con la clausula data pueden denirse por pattern matching. Del lado izquierdo de la ecuaci on pondremos la forma del argumento que esperamos recibir: un constructor seguido de una variable distinta por cada argumento que tenga. Del lado derecho, podemos usar las variables para dar el resultado de la funci on en el caso que estamos deniendo.
proximo :: Dia Dia proximo Lun = Mar proximo Mar = Mie etc. area :: FormaGeometrica Double area (Circulo r) = 2 pi r area (Rectangulo b h) = b h sumaNodos :: BinTree Double Double sumaNodos Nil = 0 sumaNodos (Branch x t1 t2) = x + sumaNodos t1 + sumaNodos t2

Los tipos que permiten acceder a sus constructores y hacer pattern matching se llaman tipos algebraicos. Los booleanos, las tuplas y las listas tambi en son tipos algebraicos! 5

fst :: (a, b) a fst (x, y) = x length :: [a] Integer length [] = [] length (_:xs) = 1 + length xs data Paridad = Par | Impar paridades :: [Integer] [Paridad] paridades [] = [] paridades (n:ns) = if par n then Par else Impar : paridades ns where par n = n rem 2 = =0

Referencias
[1] P agina de Haskell www.haskell.org [2] A tour of the Haskell Prelude, describe y da ejemplos de las funciones de uso m as com un http://undergraduate.csse.uwa.edu.au/units/230.301/ lectureNotes/tourofprelude.html [3] Haskell report es la especicaci on completa y ocial del lenguaje. http://www.haskell.org/onlinereport [4] A tour of the Haskell Syntax, una descripci on m as amigable de la sintaxis de Haskell. http://cs.anu.edu.au/Student/comp1100/haskell/tourofsyntax. html [5] A gentel introduction to Haskell, uno de los tutoriales m as famosos y bien completo. Incluye m as temas que los que vamos a ver en la materia. http://www.haskell.org/tutorial

También podría gustarte