Haskell parte 4

Sinonimos de tipo

Consiste en dar un nuevo nombre a un tipo ya existente de datos. Los dos tipos (el nuevo y el ya existente) son completamente intercambiables y compatibles.
Su sintaxis es:

type Sinonimo = expresion_tipo

Por ejemplo:

type Volante = String
type Capacidad = Int
type Modelo = String
type Coche = (Volante, Capacidad, Modelo)


Definición de nuevos tipos de datos

Se pueden crear distintos tipos de datos:

– Enumerados: son los mas sencillos. Se crea un nuevo tipo que solo puede tener unos valores predefinidos.
Su sintaxis es:

data NuevoTipo = valor1 | valor2 | valor3

Por ejemplo:

data Marca = Opel | Mercedes | Seat | Audi

Se puede aplicar patrones a los nuevos tipos de datos creados:

funcion :: Marca -> String
funcion Mercedes = “Pepinaco”
funcion Audi = “Pepino”
funcion _ = “meh”

Para que los nuevos tipos de datos se puedan mostrar por pantalla tiene que añadírsele la clausula “deriving Show”:

data Marca = Opel | Mercedes | Seat | Audi deriving Show

– Producto: se construye un nuevo tipo de datos a partir de otros.
Se define con un constructor de datos y sus componentes:

data Marca = Opel | Mercedes | Seat | Audi deriving Show
type Modelo = String
type Plazas = Int
data Coche = coche Marca Modelo Plazas deriving Show

Se pueden instanciar valores de dichos tipos para reutilizarlos a lo largo del código:

coche1 :: Coche
coche1 = coche Mercedes “Clase A” 4

Y se pueden definir funciones que los manejen, y aplicarles patrones:

cocheDePadre :: Coche -> Bool
cocheDePadre (Mercedes _ x)
| x >= 5 = True
| otherwise = False

Los tipos de dato producto se pueden además representar con campos con nombre:

data Coche = coche {marca:: Marca,
modelo:: String,
plazas:: Int}

Se instancian valores de la misma forma.
Esta sintaxis es muy similar a la representación de diccionarios (conjuntos con pares clave valor) que se encuentran en otros lenguajes como JavaScript o Python.

Para seleccionar un campo de el nuevo tipo de datos se haría utilizando el nombre del campo:

getMarca :: Coche -> Marca
getMarca c = marca c

También se puden declarar identificadores de constructores binarios simbólicos. Deben empezar por “:”.

data Complejo = Float :- Float deriving Show

c1 :: Complejo
c1 = 2.3 :- 4.5

multiplicarC :: Complejo -> Float
multiplicarC (x, y) = x*y

Además se pueden definir tipos de datos que sean comunes a varias definiciones. Se llaman uniones de productos de tipo:

type Radio = Float
type Lado = Float
data Forma = Circulo Radio | Rectangulo Lado Lado

area :: Forma -> Float
area (Circulo r) = pi * r * r
area (Rectangulo b h) = b * h

Este tipo de datos sirve para crear funciones genéricas que realicen la misma operacion sobre distintos tipos de datos.

– Tipos Recursivos: se usan para crear tipos de datos infinitos. Se usa una sintaxis similar a la de los tipos de datos comunes a varias definiciones:

data nuevoTipo = casoBase | casoRecursivo

Por ejemplo:

data Natural = Cero | Suc Natural deriving Show

En este caso estaríamos creando un tipo de datos que define un tipo Natural que puede valer Cero o el sucesor del Natural (que tambien pertenece a Natural).

Además los tipos recursivos pueden usarse para repserentar expresiones aritméticas sobre enteros:

data Expr = Valor Integer
| Expr :+: Expr
| Expr :-: Expr
| Expr :*: Expr

ej1 :: Expr
ej1 = Valor 5

ej2 :: Expr
ej2 = ej1 :+: Valor 3

ej3 :: Expr
ej3 = ej2 :*: Valor 10

si ahora ejecutaramos

ej2

devolvería

Valor 5 :+: Valor 3

– Tipos Polimórficos: permiten crear estructuras de datos que acepten cualquier tipo de dato.

data Par a = UnPar a a deriving Show

De podría hacer

UnPar 1 2

o

UnPar ‘c’ ‘b’

Pero si hicieramos por ejemplo

UnPar True ‘f’

daría error, porque hemos definido que los dos elementos tienen que ser del mismo tipo, el tipo a.
Para que pudiéramos hacer esto, el tipo polimórfico debería ser:

data Par a = UnPar a b deriving Show

Por ejemplo si quisieramos crear un tipo que fuera un arbol nario, podríamos hacerlo de la siguiente manera:

data Arbol a = Vacio | Rama a [Arbol a]

Este tipo representa un arbol que o bien puede ser vacío (Vacio) o bien tiene una raiz (a) y ramas (Rama) contenidas en una lista. Y como una rama de un arbol es a su vez un arbol, la lista contendrá árboles.


Mónada

Las mónadas son como un tipo de dato comodín.

La mónada más básica en Haskell es el dato Maybe:

data Maybe a = Nothin | Just a deriving Show

Lo que quiere decir que a o es nada (Nothing) o es solo a (Just a).

Esta mónada suele usarse para el tratamiento de excepciones.

division :: Int -> Int -> Maybe Int
division _ 0 = Nothing
division m n = Just (m `div` n)

division 5 2 = Just 2

Se han cerrado los comentarios