Tipos y estructuras de datos en los lenguajes - DSIC

Anuncio
Tipos y estructuras de datos en los
lenguajes funcionales
Salvador Lucas Alba
Departamento de Sistemas Informáticos y Computación
Universidad Politécnica de Valencia
http://www.dsic.upv.es/users/elp/slucas.html
Objetivos
• Introducir los tipos de datos como componente fundamental del estilo funcional
• Introducir los mecanismos de estructuración y abstracción de datos en los lenguajes
funcionales
• Presentar los tipos y estructuras de datos
usuales en los lenguajes funcionales
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Tipos
Motivación
• Evitar o detectar errores de programación
Un tipo caracteriza el conjunto de valores que las
expresiones de ese tipo pueden tener
• Ayudar a estructurar la información
Los tipos pueden verse como colecciones de valores
que comparten ciertas propiedades
• Ayudar a manejar estructuras de datos
Los tipos indican cómo utilizar las estructuras de
datos que comparten el mismo tipo
Tipos
Lenguajes tipificados
• Un tipo representa el conjunto de valores
que puede adoptar una variable o expresión
• En los lenguajes tipificados, las variables
adoptan un tipo (ej. Pascal, Haskell)
• Los lenguajes que no restringen el rango de
valores que pueden adoptar las variables son
no tipificados (ej. Lisp, Prolog)
Tipos
Lenguajes tipificados
En los lenguajes funcionales modernos
todas las expresiones (y subexpresiones)
tienen un tipo
Tipos
Lenguajes tipificados
• Los lenguajes tipificados incorporan un
sistema de tipos que determina si los
programas son legales
• Los sistemas de tipos se utilizan para
determinar si los programas tienen un
comportamiento adecuado
Errores
manifiestos
1/0
1/0
Errores
ocultos
Limites
Limites
vector
vector
Tipos
Lenguajes tipificados
• Un lenguaje de programación es seguro (safe)
si no son posibles errores ocultos
• Los lenguajes pueden garantizar la seguridad
mediante comprobaciones
estáticas (static check, ej. ML, Haskell), o
dinámicas (dynamic check, ej. Lisp)
Compilación
Ejecución
Tipos
Lenguajes tipificados
• En algunos lenguajes tipificados, la simple
comprobación estática de tipos puede
hacerlos seguros (ej. ML, Haskell)
• En otros casos, esto no es así (ej. Pascal, C)
Tipos
Lenguajes tipificados
El sistema de tipos de los lenguajes
funcionales modernos garantiza la escritura
de programas seguros
Tipos
Lenguajes tipificados
• En los lenguajes con tipificación explícita,
los tipos forman parte de la sintaxis
• En los lenguajes con tipificación implícita,
los tipos no forman parte de la sintaxis
Lenguajes
Expresiones
Sistema de
=
+
tipificados
de programa
tipos
Tipos
Lenguajes tipificados
El sistema de tipos de los lenguajes funcionales
modernos permite la tipificación implícita
(debido a la posibilidad de inferencia de tipos)
Sistemas de tipos
Expresiones de tipo
• Los tipos se describen mediante un lenguaje
de expresiones de tipo:
–
–
–
–
Tipos básicos o primitivos: Bool, Char, Int, ...
Variables de tipo: a, b, c, ...
Constructores de tipo: →, ×, [ ], ...
Reglas de construcción de las expresiones:
τ ::= Bool | Char | Int | ··· | t | τ → τ | τ × τ | [ τ ] | ···
Tipos
Expresiones de tipo
• Ejemplos:
Tipos básicos
• Bool, es el tipo de los valores booleanos True y
Tipos
False
monomórficos
• Int -> Int, es el tipo de la función fact, que
devuelve el factorial de un número
• [ a ] -> Int, es el tipo de la función length, que
Tipos
obtienen la longitud de una lista constituida por
polimórficos
elementos de cualquier tipo
Variable
de tipo
Constructores de tipo
Sistemas de tipos
Asertos
• Los sistemas de tipos permiten razonar
sobre tipos y asociar expresiones de tipo con
expresiones de programa:
– Tipificación M :: τ
– Equivalencia τ = τ’
τ<:τ’
– Subtipo
(M tiene tipo τ)
(τ y τ’ son equivalentes)
(τ es un subtipo de τ’)
Sistemas de tipos
Sentencias
• Las sentencias sobre las que se razona en
los sistemas de tipos son de la forma:
⊥
Γ
Φ
Contexto de
tipificación
Aserto
Γ= ∅, x1::τ1, x2::τ2, ..., xn::τn
para n≥0
Con variables libres
x1, x2, ..., xn
Sistemas de tipos
Sentencias
• Ejemplo:
True::Bool
⊥
∅
x+1::Int
⊥
∅, x::Int
El tipo de True es Bool
El tipo de x+1 es Int si
el tipo de x es Int
Sistemas de tipos
Sistema formal
• Las reglas del sistema de tipos tienen la
forma general:
(Nombre)
Φ1 ... Γn
⊥
Γ
⊥
⊥
Γ1
Φn (condiciones)
Φ
Sistemas de tipos
Sistema formal
• Ejemplo:
(Env ∅)
El contexto de tipificación
vacío siempre es válido
◊
⊥
∅
Sistemas de tipos
Sistema formal
• Ejemplo (reglas de tipificación):
(Val n)
⊥
Γ
◊ (n=0, ±1, ±2...)
⊥
Γ
n::Int
El tipo de un valor entero
es Int en cualquier contexto de tipificación válido
Sistemas de tipos
Sistema formal
• Ejemplo (reglas de tipificación):
(Val +)
N::Int
M+N::Int
⊥
Γ
Γ
⊥
M::Int
⊥
Γ
Si las expresiones M y N
son de tipo entero en Γ,
también M+N lo es
Tipos
Lenguajes tipificados
Un sistema de tipos es un conjunto de
reglas de tipo
Sistemas de tipos
Sistema formal
• Una derivación en un sistema de tipos es un
árbol (invertido) de sentencias
• Cada una se obtiene de las inmediatamente
superiores por aplicación de una regla
• Una sentencia válida es la que se puede
obtener como raíz de una derivación
Sistemas de tipos
Sistema formal
• Ejemplo:
1+2::Int
⊥
∅
∅
(por Env ∅)
2::Int
(por Val n)
⊥
(por Val n)
◊
⊥
∅
(por Env ∅)
1::Int
⊥
∅
◊
⊥
∅
(por Val +)
Sistemas de tipos
Problemas de tipificación
• Dos problemas fundamentales sobre tipificación de expresiones de programa:
⊥
– Comprobación de tipos (type checking): Dados
M, Γ y τ, comprobar si Γ M :: τ es válida
– Inferencia de tipos (type inference o type
deduction): Dada M, obtener, en su caso, Γ y τ
de forma que Γ M :: τ sea válida
⊥
Sistemas de tipos
Problemas de tipificación
• En ambos casos, es esencial disponer de
algoritmos para realizar dichas tareas:
– Algoritmo de comprobación de tipos
(typechecking algorithm)
– Algoritmo de inferencia de tipos
(type inference algorithm)
• La existencia y eficacia de éstos depende
mucho del sistema de tipos
Sistemas de tipos
Problemas de tipificación
Haskell utiliza el sistema de tipos (polimórficos)
de Hindley-Milner que admite comprobación
de tipos (Mycroft) e inferencia de tipos (Milner)
Sistemas de tipos
Problemas de tipificación
• El sistema de tipos de Hindley-Milner tiene
sus limitaciones: la función
selfapplication f = f f
no admite ningún tipo dentro de este sistema
Sistemas de tipos
Problemas de tipificación
• Ejemplo: Dadas las ecuaciones
fun f lista1 lista1 = f lista1 + f lista2
imposible = fun length [1,2,3] “abc”
la expresión imposible no admite ningún
tipo dentro de este sistema
Sistemas de tipos
Problemas de tipificación
La elección de un sistema de tipos
puede limitar la expresividad del lenguaje
Sistemas de tipos
Problemas de tipificación
• Los algoritmos de comprobación de tipos
(Mycroft) e inferencia de tipos (Milner) no
son totalmente equivalentes
Sistemas de tipos
Problemas de tipificación
• Ejemplo: consideremos la ecuación
g x = 1:g (g ‘c’)
El algoritmo de Milner falla al tratar de
encontrar el tipo de g. Especificando
g :: a -> [Int]
el intérprete (que utiliza el algoritmo de
Mycroft en ese caso) acepta la definición
Sistemas de tipos
Problemas de tipificación
• Ejemplo: consideremos la ecuación
gx=g1
El algoritmo de Milner infiere el tipo
g :: Num a => a -> b
mientras que el algoritmo de Mycroft acepta
la tipificación explícita (más general)
g :: a -> b
Sistemas de tipos
Problemas de tipificación
A pesar de la posibilidad de tipificación
implícita, a veces es recomendable dar
los tipos de las funciones explícitamente
Polimorfismo
Polimorfismo paramétrico
• Los tipos en cuya expresión de tipo no
aparecen variables de tipo se denominan
monotipos o tipos monomórficos
• Los tipos en cuya expresión de tipo aparecen
variables se denominan politipos o tipos
polimórficos (polimorfismo paramétrico)
• Un tipo polimórfico representa un número
infinito de monotipos
Polimorfismo
Polimorfismo paramétrico
• Ejemplo: la función
length :: [a] -> Int
puede verse como una función con infinitos
monotipos
[Int] -> Int,
[Bool] -> Int,
[Int -> Int] -> Int, ...
Polimorfismo
Polimorfismo paramétrico
• Ejemplo: La implementación de
length :: [a] -> Int
es única:
length [ ]
=0
length (x:xs) = 1+length xs
y resulta válida para todos los usos de la
función
Polimorfismo
Polimorfismo paramétrico
• Con un sistema de tipos polimórficos, el
algoritmo de inferencia de tipos intenta
obtener el tipo principal de las expresiones
• El tipo principal es el tipo más general
capaz de capturar todos los usos válidos
de la expresión
Polimorfismo
Polimorfismo paramétrico
El sistema de tipos de Hindley-Milner
asegura que toda expresión tipificable tiene
un tipo principal único
Polimorfismo
Sobrecarga
• A veces nos interesa sobrecargar el uso de
ciertos operadores, aplicándolos sobre
argumentos de distintos tipos, aunque de
forma limitada
• Otras veces, no tiene sentido asignar un
politipo a un operador si no podemos
implementar todas sus concreciones
Polimorfismo
Sobrecarga
• Este tipo de polimorfismo se denomina
polimorfismo ad-hoc o sobrecarga
(overloading)
Polimorfismo
Sobrecarga
• Ejemplo: los operadores aritméticos (+), (-),
(*), (/), ..., suelen estar sobrecargados:
(+) :: Int -> Int -> Int
(+) :: Float -> Float -> Float
(+) :: Complex -> Complex -> Complex
corresponden a distintos usos de (+). Otro:
(+) :: Int -> Float -> Float
Polimorfismo
Sobrecarga
• El operador (+) no puede recibir el politipo
(+) :: a -> a -> a
porque implicaría dotar de significado a la
‘suma’ de caracteres, funciones, listas, etc.,
lo cual puede interesarnos o no
Polimorfismo
Sobrecarga
• Ejemplo: El operador de igualdad (==), aun
teniendo una semántica bien definida, no es
implementable en algunos casos.
¿Cómo determinar (efectivamente)
si dos funciones son iguales?
Polimorfismo
Sobrecarga
• Matemáticamente: sean
f:D→E
y
g:D→E
dos funciones. Tenemos que
f =D → E g
si y sólo si
∀x∈D, f(x) =E f(x)
Si D es infinito, o f no es computable,
=D → E puede no ser decidible
Polimorfismo
Sobrecarga
• El operador (==) no puede recibir el politipo
(==) :: a -> a -> Bool
porque tendríamos que implementar la
comprobación de igualdad para todos los
tipos; en particular para las funciones:
(==) :: (a->b) -> (a->b) -> Bool
Polimorfismo
Sobrecarga
En Haskell, el polimorfismo ad-hoc se
implementa mediante el concepto de clase
Polimorfismo
Sobrecarga
• Una clase es una colección de tipos
• Todos los tipos pertenecientes a una clase
deben tener definidas ciertas operaciones
Polimorfismo
Sobrecarga
• Ejemplo:
– Los miembros de la clase Eq deben definir las
operaciones (==) y (/=) para comprobar si dos
elementos son iguales o distintos
– Los miembros de la clase Ord deben tener
definidas, además de (==) y (/=), las relaciones
(<) y (<=) para comparar elementos entre sí
Polimorfismo
Sobrecarga
class Eq a where
-- simplificado
(==), (/=) :: a -> a -> Bool
class Eq a => Ord a where -- simplificado
(<), (<=), (>), (>=) :: a -> a -> Bool
Ord es una
subclase de Eq
Polimorfismo
Sobrecarga
• De acuerdo con la declaración anterior, el
tipo (sobrecargado) de (==) es
(==) :: Eq a => a -> a -> Bool
que se interpreta como sigue:
si a es un tipo de la clase Eq, el tipo de
(==) es a -> a -> Bool
Polimorfismo
Sobrecarga
• Algunas clases predefinidas de Haskell son:
Eq: tipos con comprobación de igualdad
Ord: tipos con operadores de comparación
Enum: tipos cuyos valores son secuenciables
Show: tipos cuyos valores son convertibles en
cadenas de caracteres
– Num, Integral, Fractional, Real, Floating,
RealFrac, RealFloat: clases numéricas
–
–
–
–
Polimorfismo
Sobrecarga
• Es posible añadir nuevos tipos a una clase,
si particularizamos las operaciones propias
de ésta para los valores del nuevo tipo
Polimorfismo
Sobrecarga
• Ejemplo: consideremos el tipo
data Nat = Cero | S Nat deriving Show
Podemos añadirlo a la clase Eq:
instance Eq Nat where
Cero== Cero = True
S n == S m = m == n
_
== _
= False
Polimorfismo
Sobrecarga
• Ejemplo: En realidad, bastaría con escribir
data Nat = Cero | S Nat
deriving (Eq, Show)
Polimorfismo
Sobrecarga
• La clase Num se define como
class (Eq a, Show a) => Num a where
(+),(-),(*) :: a -> a -> a
¡¡Simplificado!!
Polimorfismo
Sobrecarga
• Podemos añadir el tipo Nat a la clase Num:
instance Num Nat where
No es preciso Cero + n = n
definir todas
(S n) + m = S (n+m)
las operaciones
Cero * n = Cero
(¡¡pero no se
podrán usar!!)
(S n) * m = m + (n*m)
Polimorfismo
Sobrecarga
• Ahora podríamos escribir, directamente:
fact Cero = S Cero
fact (S n) = (S n) * fact n
¡¡Sobrecargado!!
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Tipos básicos
•
Los tipos básicos proporcionados por
Haskell son:
–
–
–
–
–
Booleanos
Caracteres
Tuplas
Cadenas
Tipos numéricos
Tipos básicos
Booleanos
•
•
Los valores del tipo Bool son True y
False
El tipo Bool pertenece a las clases
Bounded, Enum, Eq, Ord y Show,
entre otras
Tipos básicos
Booleanos
•
El perfil de la clase Enum es:
class Enum a where
succ,pred
:: a -> a
toEnum
:: Int -> a
fromEnum
:: a -> Int
¡¡Simplificado!!
Tipos básicos
Booleanos
•
Operaciones usuales para Bool (en
Haskell):
– Conjunción:&& :: Bool -> Bool -> Bool
– Disyunción:| | :: Bool -> Bool -> Bool
– Negación: not :: Bool -> Bool
Tipos básicos
Caracteres
•
Los valores del tipo Char son los
caracteres:
–
–
–
–
–
–
‘a’, ‘b’, ..., ‘A’, ‘B’, ..., ‘1’, ‘2’, ...
‘\a’, ‘\b’, ‘\f’, ‘\n’, ‘\r’, ...
‘\BEL’, ‘\BS’, ‘\FF’, ‘\LF’, ‘\CR’, ...
‘\7’, ‘\8’, ‘\12’, ‘\10’, ‘\13’, ...
‘\o7’, ‘\o10’, ‘\o14’, ‘\o12’, ‘\o15’
‘\x7’, ‘\x8’, ‘\xC’, ‘\xA’, ‘\xD’, ...
Tipos básicos
Caracteres
•
•
El tipo Char pertenece a Bounded,
Enum, Eq, Ord y Show
Operaciones usuales para Char:
– isAlpha, isAlphaNum, isAscii, isDigit,
isLower, isPrint, isUpper :: Char -> Bool
– toLower, toUpper :: Char -> Char
– chr :: Int -> Char
-- toEnum
– ord :: Char -> Int
-- fromEnum
Tipos básicos
Tuplas
•
El tipo polimórfico (a,b) (en general,
(a1,..., an) ) permite agrupar valores
procedentes de tipos distintos:
(True,False) :: (Bool,Bool)
(True,’a’) :: (Bool,Char)
((True,False),’a’) :: ((Bool,Bool),Char)
(isDigit,’a’,1) :: (Char -> Bool, Char,Int)
Tipos básicos
Tuplas
•
•
El tipo tupla pertenece a las clases Eq,
Ord, Show y Enum, entre otras
Operaciones usuales sobre tuplas:
– Proyección izq:
– Proyección der:
fst :: (a,b) -> a
snd :: (a,b) -> b
¡¡Sólo con pares!!
Tipos básicos
Cadenas
•
•
Los valores del tipo String son las
cadenas de caracteres: “”, “1&bA”,
“Esta frase \10ocupa dos lineas”
En realidad, String es un tipo sinónimo:
type String = [Char]
Tipos básicos
Cadenas
•
El tipo String pertenece a las clases Eq,
Ord y Show, entre otras
Tipos numéricos
Números en Haskell
•
Los tipos numéricos en Haskell son:
–
–
–
–
Int, Integer: Números enteros
Float, Double: Números reales
Ratio: Números racionales
Complex: Números complejos
Preludio
Estándar
Librerías
Tipos numéricos
Números enteros
•
Los valores del tipo Int son los enteros de
rango acotado:
0, 45, -3452, 2147493647
•
•
El límite es maxBound :: Int
El tipo Int pertenece a la clase Bounded
class Bounded a where
minBound :: a
maxBound :: a
Tipos numéricos
Números enteros
•
El tipo Int también pertenece a las clases
Enum, Eq, Ord y Show, además de a las
clases numéricas Num, Real e Integral
Tipos numéricos
Números enteros
class (Eq a, Show a) => Num a where
(+),(-),(*)
:: a -> a -> a
negate
:: a -> a
abs,signum
:: a -> a
fromInteger
:: Integer -> a
Tipos numéricos
Números enteros
class (Num a, Ord a) => Real a where
toRational
:: a -> Rational
class (Real a, Enum a) => Integral a where
quot,rem,div,mod :: a -> a -> a
quotRem, divMod :: a -> a -> (a,a)
toInteger
:: a -> Integer
Tipos numéricos
Números enteros
•
•
Los valores del tipo Integer son los
enteros de rango arbitrario
La aritmética con Integer es más precisa
que con Int, pero más costosa
Tipos numéricos
Números enteros
•
El tipo Integer pertenece a las clases
Enum, Eq, Ord y Show (pero no a
Bounded),
además de a las clases numéricas
Num, Real e Integral
Tipos numéricos
Números reales
•
Los valores del tipo Float son los números
en coma flotante de precisión simple:
0.31426, -23.12, 567.347, 4523.0
231.61e7, 231.6e-2, -3.412e03
Tipos numéricos
Números reales
•
El tipo Float pertenece a las clases
Enum, Eq, Ord y Show (no a
Bounded),
además de a las clases numéricas
Num, Real, Fractional, Floating,
RealFrac y RealFloat
Tipos numéricos
Números reales
class (Num a) => Fractional a where
(/)
:: a -> a -> a
recip
:: a -> a
fromRational :: Rational -> a
Tipos numéricos
Números reales
class (Fractional a) => Floating a where
pi
:: a
exp,log,sqrt
:: a -> a
(**),logBase
:: a -> a -> a
sin,cos,tan,
asin,acos,atan,
sinh,cosh,tanh,
asinh,acosh,atanh :: a -> a
Tipos numéricos
Números reales
class (Real a,Fractional a) => RealFrac a
where
properFraction :: (Integral b) => a -> (b,a)
truncate,round :: (Integral b) => a -> b
ceiling,floor
:: (Integral b) => a -> b
Tipos numéricos
Números reales
class (RealFrac a,Floating a) => RealFloat a
where
floatRadix
:: a -> Integer
floatDigits
:: a -> Int
floatRange
:: a -> (Int,Int)
decodeFloat :: a -> (Integer,Int)
encodeFloat :: Integer -> Int -> a
Tipos numéricos
Números reales
class (RealFrac a,Floating a) => RealFloat a
where
-- Continuación
exponent
:: a -> Int
significand
:: a -> a
scaleFloat
:: Int -> a -> a
isNaN,isInfinite:: a -> Bool
isDenormalized:: a -> Bool
isIEEE
:: a -> Bool
Tipos numéricos
Números reales
Otras operaciones de interés son:
(^) :: (Integral b, Num a) => a -> b -> a
Potencia con exponente entero
(^^) :: (Integral b, Fractional a) => a -> b -> a
Potencia con exponente racional
Tipos numéricos
Números reales
•
•
Los valores del tipo Double son los
números en coma flotante de precisión
doble
El tipo Double pertenece a las mismas
clases que Float
Tipos numéricos
Números racionales y complejos
•
•
•
Los tipos Ratio y Rational, para trabajar
con números racionales, se definen en la
librería Ratio de Haskell 98
El tipo Complex, para trabajar con
números complejos, se definen en la
librería Complex de Haskell 98
La librería Numeric de Haskell 98
describe funciones numéricas adicionales
Tipos numéricos
Num
Int,Integer,Float,Double
Real
Fractional
Int,Integer,Float,Double
Float,Double
Integral
RealFrac
Floating
Int,Integer
Float,Double
Float,Double
RealFloat
Float,Double
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Tipos
Tipos algebraicos
• Los tipos algebraicos se definen junto con
los valores que éstos contienen
• Ejemplos:
•
•
•
•
data Color = Red | Green | Blue
data Laboral = Lu | Ma | Mi | Ju | Vi
data TreeInt = L Int | B TreeInt TreeInt
data Tree t = L t | B (Tree t) (Tree t)
Tipos
Tipos algebraicos
• Los tipos algebraicos se definen junto con
los valores que éstos contienen
• Ejemplos:
•
•
•
•
data Color = Red | Green | Blue
data Laboral = Lu | Ma | Mi | Ju | Vi
data TreeInt = L Int | B TreeInt TreeInt
data Tree t = L t | B (Tree t) (Tree t)
Constructores de tipos
Tipos
Tipos algebraicos
• Los tipos algebraicos se definen junto con
los valores que éstos contienen
• Ejemplos:
•
Simples
•
•
Estructurados
•
data Color = Red | Green | Blue
data Laboral = Lu | Ma | Mi | Ju | Vi
data TreeInt = L Int | B TreeInt TreeInt
data Tree t = L t | B (Tree t) (Tree t)
Constructores de datos
Tipos
Tipos algebraicos
• Los tipos algebraicos se definen junto con
los valores que éstos contienen
• Ejemplos:
•
•
•
•
data Color = Red | Green | Blue
data Laboral = Lu | Ma | Mi | Ju | Vi
data TreeInt = L Int | B TreeInt TreeInt
data Tree t = L t | B (Tree t) (Tree t)
Polimórfico
Variables de tipo
Tipos
Tipos algebraicos
• Los valores se obtienen considerando la
definición de tipo como una gramática:
– Los constructores de datos son símbolos
terminales
– Los constructores de tipo son símbolos no
terminales
• Los valores del tipo son los términos del
lenguaje generado por la gramática
Tipos
Tipos algebraicos
• Ejemplo:
Int := 0 | 1 | 2 | 3 | ··· | -1 | -2 | -3 | ···
TreeInt := L Int | B TreeInt TreeInt
Valores de este tipo son:
L 1, L -10, B (L 1) (L 10), B (B (L 1) (L1)) (L -1)
Tipos
Tipos algebraicos
• Ejemplo de valor del tipo TreeInt
1
4
2
3
(B (L 1) (B (B (L 2) (L 3)) (L 4)))
Tipos
Tipos algebraicos
• Las siguientes expresiones:
L (1+1)
B (B (L 1) (L (length “ab”))) (L (fact 2))
son del tipo TreeInt, pero no son
valores (contienen símbolos no
constructores)
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Tipos funcionales
• Los tipos funcionales (que involucran el
constructor de tipo →) son muy importantes
en programación funcional
• Ejemplo:
Int -> Int
a -> Bool
Num a => a -> a -> a
(a -> b) -> [a] -> [b]
Tipos funcionales
Valores funcionales
• Los valores funcionales pueden
especificarse de dos formas:
– explícitamente: mediante expresiones lambda
– implícitamente: mediante ecuaciones
Definición de funciones
Expresiones lambda
• Una función f se describe mediante una
expresión lambda de la forma
\ x1 · · · xk -> e
• Las variables x1, ..., xk son distintas entre sí
y las únicas que aparecen en la expresión e
Definición de funciones
Expresiones lambda
• Ejemplo
\ x y -> x+y
\ x -> 2*x
\ x -> True
\ m n -> B (L m) (L n)
Definición de funciones
Expresiones lambda
La definición de funciones recursivas es
problemática (¡aunque no imposible!)
Definición de funciones
Ecuaciones
• En los lenguajes funcionales, lo normal es
definir las funciones mediante ecuaciones
empleando (y combinando) distintas técnicas:
–
–
–
–
–
parámetros formales
guardas
ajuste de patrones
distinción de casos
cláusulas where
Definición de funciones
Parámetros formales
• Una función f se describe mediante
ecuaciones de la forma:
f x1 · · · xk = r
• Las variables x1, ..., xk son distintas entre sí
y las únicas que aparecen en la parte
derecha r
Definición de funciones
Parámetros formales
• Ejemplos:
doble x
triple x
seisveces x
fact n
= x+x
= 3*x
= doble (triple x)
= if n==0 then 1 else
n*fact (n-1)
Definición de funciones
Parámetros formales
• Ejemplos:
doble x = x + x
triple x = 3 * x
Funciones primitivas
Definición de funciones
Parámetros formales
• Ejemplos:
doble x
= x+x
triple x
= 3*x
seisveces x = doble (triple x)
Otras funciones de usuario
Definición de funciones
Parámetros formales
• Ejemplos:
doble x
= x+x
triple x
= 3*x
seisveces x = doble (triple x)
= if n==0 then 1 else
fact n
n*fact (n-1)
Recursividad
Definición de funciones
Parámetros formales y guardas
• Una función f se describe mediante
ecuaciones de la forma:
f x1 · · · xk | c = r
donde c es una expresión booleana
Definición de funciones
Parámetros formales y guardas
• Ejemplos:
fact n |
|
sign x |
|
|
n==0 = 1
n>0 = n*fact (n-1)
x<0 = neg
x==0 = cero
x>0 = pos
Definición de funciones
Parámetros formales y guardas
• Ejemplos:
fact n |
|
sign x |
|
|
n==0 = 1
n>0 = n*fact (n-1)
x<0 = neg
x==0 = cero
x>0 = pos
Guardas
Definición de funciones
Ajuste de patrones
• Una función f se describe mediante
ecuaciones de la forma:
f p1 · · · pk = r
• Los patrones p1, ..., pk son términos
constituidos por constructores de datos y
variables
Definición de funciones
Ajuste de patrones
• Ejemplos:
length []
=0
length (x:xs) = 1+length xs
data Nat = Cero | S Nat
first Cero _
= []
first (S n) (x:xs) = x:(first n xs)
Definición de funciones
Ajuste de patrones
• Ejemplos:
length []
=0
length (x:xs) = 1+length xs
data Nat = Cero | S Nat
first Cero _
= []
first (S n) (x:xs) = x:(first n xs)
Patrones
Patrones
Definición de funciones
Ajuste de patrones
• Una expresión e se ajusta a un patrón p
(pattern matching) si e puede verse como
una concreción de p (dando ciertos valores
a las variables libres de p)
Definición de funciones
Ajuste de patrones
• Ejemplo: la expresión S (S Cero) se ajusta
al patrón S x pero no al patrón Cero
S (S Cero)
{x := S Cero}
Sx
S (S Cero)
X
Cero
Definición de funciones
Ajuste de patrones
El ajuste de patrones permite clasificar datos
y explorar / recuperar subestructuras de los mismos
Definición de funciones
Distinción de casos
• Una función f se describe mediante
ecuaciones de la forma:
f p1 · · · pk = case x of
q1 -> e1
...
qn -> en
• Donde p1 · · · pk, q1 · · · qn son patrones, x
es una variable y e1 · · · en expresiones
Definición de funciones
Distinción de casos
• Ejemplo:
length xs = case xs of
[ ] -> 0
(y:ys) -> 1+length ys
Definición de funciones
Cláusulas where
• Una función f se describe mediante
ecuaciones de la forma:
f p1 · · · pk = e where
l1 = r1
...
ln = rn
• Donde l1 · · · ln son patrones o partes
izquierdas de definiciones de función, y
r1 · · · rn son expresiones
Definición de funciones
Cláusulas where
• Ejemplo:
raicesEc2 a b c = ((-b+d)/a’,(-b-d)/a’)
where
d = sqrt(b^2-4*a*c)
a’ = 2*a
Orden superior
Funciones como ciudadanos de primera clase
• En programación funcional, las funciones
son ‘ciudadanos de primera clase’ (first
class citizens):
Orden superior
Funciones como ciudadanos de primera clase
• En programación funcional, las funciones
son ‘ciudadanos de primera clase’ (first
class citizens):
– Pueden ser pasadas, como argumentos, a otras
funciones
Orden superior
Funciones como ciudadanos de primera clase
• En programación funcional, las funciones
son ‘ciudadanos de primera clase’ (first
class citizens):
– Pueden ser pasadas, como argumentos, a otras
funciones
– Pueden ser devueltas como resultado de una
llamada a función
Orden superior
Funciones como ciudadanos de primera clase
map aplica una función f
• Ejemplos:
a cada elemento de una lista
map f []
= []
map f (x:xs) = (f x):map f xs
add x y
add2
= x+y
= add 2
aplicación
parcial
add2 añade 2 al número
que se le pasa como
argumento
Orden superior
Currificación
• A cada función (sobre k-tuplas)
f: D1 × D2 × ··· × Dk → E
le corresponde una función
fC: D1 → (D2 → ( ··· → (Dk → E)···)
que a cada valor de D1 le asocia una función
de k-1 argumentos (y viceversa)
• fC es la versión currificada de f
Orden superior
Currificación
• Ejemplo:
map :: (a -> b) -> [a] -> [b]
if :: Bool -> a -> a -> a
+ :: Num a => a -> a -> a
Orden superior
Currificación
• El operador -> es asociativo por la derecha
a -> b -> c
a -> (b -> c)
equivale a
y difiere de (a -> b) -> c
• El operador de aplicación (a veces denotado
como @) es asociativo por la izquierda
f ab
equivale a (f a) b
y difiere de f (a b)
Orden superior
Currificación
• En programación funcional ésto facilita la
aplicación parcial de una función: si
f :: a -> b -> c
Entonces, si e::a, escribir
fe
tiene sentido pleno: se trata de una función
f e :: b -> c
Orden superior
Currificación
• Ejemplo: la expresión
map add2 [1,2]
es válida en un lenguaje como Haskell, y
sería equivalente a
map (add 2) [1,2]
o incluso
Sección
map (+ 2) [1,2]
Desarrollo
1.
2.
3.
4.
Tipos
Tipos básicos y tipos numéricos
Tipos algebraicos
Tipos funcionales: orden superior,
definición de funciones
5. Listas y árboles
6. Tipos abstractos de datos
Bibliografía
[Car97] L. Cardelli. Type Systems.
[PE93] R. Plasmeijer and M. van Eekelen. Functional
Programming and Parallel Graph Rewriting. AddisonWesley, Reading, MA, 1993
[Rea93] C. Reade. Elements of Functional Programming.
Addison-Wesley, Reading, MA, 1993
λ
:=
Descargar