Pattern matching
+ Tipos enumerados
Taller de ´Algebra I
Pattern matching
Pattern matching
Elpattern matchinges un mecanismo que nos permite asociar una definici´on de una funci´on solo a ciertos valores de sus par´ametros: aquellos que se correspondan con cierto patr´on.
Pattern matching
en
Bool
Si quisi´eramos definir la funci´onnot(negaci´on l´ogica), podr´ıamos hacerlo as´ı: not :: B o o l - > B o o l
not x | x == T r u e = F a l s e
| x == F a l s e = T r u e
Ac´a,xes unpatr´on: es el menos restrictivo posible, ya que se corresponde con cualquier valor de tipoBool.
El tipoBooladmite otros dos patrones m´as restrictivos: TrueyFalse. Usando estos patrones, podemos redefinirnotde esta forma:
not :: B o o l - > B o o l not T r u e = F a l s e not F a l s e = T r u e
Pattern matching
: explicaci´
on gr´
afica
La siguiente funci´on toma un pol´ıgono y nos dice cu´antos lados tiene:
La funci´on que nos dice la cantidad de lados
c a n t i d a d L a d o s = 3 c a n t i d a d L a d o s = 4 c a n t i d a d L a d o s = 5 c a n t i d a d L a d o s = 6 c a n t i d a d L a d o s = 7 c a n t i d a d L a d o s = 8 c a n t i d a d L a d o s = 9 c a n t i d a d L a d o s = 10 . . .
Pattern matching
en
Integer
En el tipoInteger, todos los n´umeros son patrones v´alidos. Por ejemplo, podemos reescribir la funci´onfactorial :: Integer -> Integer
f a c t o r i a l n | n == 0 = 1
| o t h e r w i s e = n * f a c t o r i a l ( n - 1)
usandopattern matching:
f a c t o r i a l 0 = 1
f a c t o r i a l n = n * f a c t o r i a l ( n - 1)
Parareducircualquier expresi´on que contengafactorial, Haskell compara, en orden de arriba hacia abajo, cada patr´on con los valores de los par´ametros, y utiliza el primero que funcione.
Si el patr´on tienevariables libres, seligana los valores de los par´ametros.
Todos los tipos de datos admiten el patr´on_, que se corresponde con cualquier valor, pero no liga ninguna variable. Lo usamos cuando no nos importa el valor de alg´un par´ametro. Por ejemplo:
e s L a R e s p u e s t a A T o d o :: I n t e g e r - > B o o l
e s L a R e s p u e s t a A T o d o 42 = T r u e
Pattern matching
en tuplas
Elpattern matchingtambi´en nos permite escribir de forma m´as clara definiciones que involucrentuplas.
Podemos usar patrones para descomponer la estructura de una tupla en los elementos que la forman y ligar cada uno de ellos a una variable distinta.
Por ejemplo, la siguiente definici´on:
s u m a V e c t o r i a l :: (Float, F l o a t) - > (Float, F l o a t) - > (Float, F l o a t) s u m a V e c t o r i a l t1 t2 = (fst t1 + fst t2 , snd t1 + snd t2 )
puede reescribirse como:
s u m a V e c t o r i a l :: (Float, F l o a t) - > (Float, F l o a t) - > (Float, F l o a t) s u m a V e c t o r i a l ( x1 , y1 ) ( x2 , y2 ) = ( x1 + x2 , y1 + y2 )
En este caso, el patr´on(x1, y1)se corresponde con la primera tupla, y las variablesx1e
y1se ligan con cada una de las componentes de la tupla. Algo an´alogo pasa con la segunda tupla y el patr´on(x2, y2).
Ejercicios
EjerciciosI ¿Son correctas las siguientes definiciones? ¿Por qu´e? f a c t o r i a l 0 = 1
f a c t o r i a l ( n + 1) = ( n + 1) * f a c t o r i a l n i g u a l e s :: I n t e g e r - > I n t e g e r - > B o o l
i g u a l e s x x = T r u e
i g u a l e s x y = F a l s e
I Escribir las definiciones de las siguientes funciones,utilizando pattern matching. Tratar de evaluar la m´ınima cantidad de par´ametros necesaria.
I yLogico :: Bool -> Bool -> Bool, la conjunci´on l´ogica.
I oLogico :: Bool -> Bool -> Bool, la disyunci´on l´ogica.
I implica :: Bool -> Bool -> Bool, la implicaci´on l´ogica.
I sumaGaussiana :: Integer -> Integer,
que toma un entero no negativo y devuelve la suma de todos los enteros positivos menores o iguales que ´el.
I algunoEsCero :: (Integer, Integer, Integer) -> Bool, que devuelve True sii alguna de las componentes de la tupla es 0.
I productoInterno :: (Float, Float) -> (Float, Float) -> Float,
que dados dos vectoresv1= (x1,y1),v2= (x2,y2)∈R2, calcula su producto interno hv1,v2i=x1x2+y1y2.
Tipos enumerados
Untipo enumeradoes un tipo de datos cuyos valores posibles est´an dadospor extensi´on.
El tipoBooles un ejemplo de tipo enumerado; podemos definirlo as´ı: d a t a B o o l = F a l s e | T r u e
I El t´erminodataindica que estamos definiendo un tipo de datos.
I Booles el nombre del nuevo tipo de datos.
I A la derecha del=tenemos todos losconstructores. Cada uno de ellos es un valor posible del nuevo tipo. Podemos pensarlos como funciones queno reciben par´ametrosy devuelven una instancia del tipo que estamos definiendo.
I La barra vertical (|) separa los distintos constructores.
Cada uno de los constructores constituye un patr´on v´alido a la hora de hacerpattern matching.
Ejercicio: El tipo
Dia
Ejercicios
I Definir un tipo de datos enumerado,Dia, cuyos valores posibles sean los d´ıas de la semana:
{Domingo, Lunes, Martes, Mi´ercoles, Jueves, Viernes, S´abado}.
I Definir las siguientes funciones:
I esFinde :: Dia -> Bool,
que determina si el d´ıa es parte del fin de semana.
I esDiaHabil :: Dia -> Bool, que determina si el d´ıa es un d´ıa h´abil.
I diaSiguiente :: Dia -> Dia,
que devuelve el d´ıa siguiente al recibido por par´ametro.
Repaso: Clases de tipos
Haciendo memoria
Lasclases de tipossonconjuntos de tipos de datosque tienen definidas determinadas operaciones.
Algunas clases de tipos ´utiles:
I Eqes la clase de los tipos cuyos elementos puedencompararse por igualdad; tienen definidas las funciones(==)y(\=), que devuelven unBool.
I Ordes la clase de los tipos cuyos elementos puedenordenarse; tienen definidas funciones como(<=),(>=),(<)y(>), que devuelven unBool.
I Showes la clase de los tipos cuyos elementos puedenmostrarse por pantalla; tienen definida la funci´onshow, que devuelve unString.
Nuestros tipos y las clases de tipos
Cuando definimos un tipo de datos nuevo, no forma parte deninguna clase.
¡Esto quiere decir que Haskell no sabe c´omo mostrar un elemento de nuestro tipo por pantalla! Tampoco puede, por ejemplo, saber si dos elementos son o no iguales.
Para que nuestro tipo sea parte de una clase, tenemos quedefinirlas funciones necesarias. Por ejemplo:
I Para que un tipotsea parte deEq, hay que definir una funci´on(==) :: t -> t -> Bool.
I Para que un tipotsea parte deOrd, hay que definir una funci´on(<=) :: t -> t -> Bool.
I Para que un tipotsea parte deShow, hay que definir una funci´onshow :: t -> String.
La forma m´as sencilla de hacer esto es dejar que Haskellinfierala definici´on de estas funciones. Para esto, agregamos a la definici´on del tipo la palabra clavederiving, seguida de las clases que queramos.
Nuestros tipos y las clases de tipos
Ejercicios
I Hacer queDiasea parte de las clasesEq,OrdyShow.
d a t a Dia = D o m i n g o | ... | S a b a d o d e r i v i n g (Eq, Ord, S h o w)
I ¿C´omo define Haskell, por defecto, las funciones(==),(<=)yshow?
Ejercicio: Logo
Teniendo en cuenta las siguientes definiciones: t y p e P o s i c i o n = (Integer, I n t e g e r)
d a t a D i r e c c i o n = N o r t e | Sur | E s t e | O e s t e
t y p e T o r t u g a = ( P o s i c i o n , D i r e c c i o n )
programar estas funciones: 1 arrancar :: Tortuga,
que representa una tortuga en el(0,0)mirando hacia elSur.
2 girarDerecha :: Tortuga -> Tortuga,
que gira la tortuga 90 grados a la derecha, sin moverla de lugar.
3 avanzar :: Tortuga -> Integer -> Tortuga,
que hace avanzar a la tortuga la distancia indicada, en la direcci´on hacia donde est´a mirando.