Versión impresión - Dpto. Ciencias de la Computación e Inteligencia

advertisement
Tema 1: Introducción
A. Chávez González y C. Graciani Dı́az
Departamento de Ciencias de la Computación e Inteligencia Artificial
Grado en Matemáticas. Informática. Curso 2010-2011
Programación Funcional
Introducción
Caracterı́sticas
La Programación Funcional aparece como solución a
necesidades en campos como IA, Cálculo simbólico,
demostraciones de teoremas, procesamiento del lenguaje
natural, ...
Los cálculos se ven como una función matemática que hace
corresponder entradas y salidas
Método básico de computación: aplicación de funciones a sus
argumentos
Los bucles se modelan mediante recursión.
Lenguaje de programación funcional: soporta y potencia el
estilo funcional
Funcional vs Imperativa
Hoja de Cálculo: aproximación al lenguaje funcional
Se especifica cada celda en términos de los valores de otras
celdas. El objetivo es qué hay que calcular, no cómo
No especificamos el orden en que deben calcularse las celdas,
pero los cálculos respetan la dependencia entre operaciones
No indicamos a la Hoja de Cálculo cómo manejar la memoria
pero presenta un plano de celdas infinito y sólo utiliza la
memoria de las celdas en uso
Especificamos el valor de una celda por una expresión cuyas
partes pueden evaluarse en cualquier orden en vez de una
secuencia de comandos que calculan los valores
Un lenguaje para PF
Un lenguaje para Programación Funcional
Caracterı́sticas de un buen lenguaje funcional
Modo de evaluación (impaciente/perezosa)
Que disponga de funciones de primer orden o orden superior
Inferencia de tipos
Polimorfismo frente a lenguajes no tipificados o con
tipificación dinámica, como LISP o SCHEME
Antecedentes
Lenguajes de orden superior
HOPE (Burstall et al., 1980)
MIRANDA (Turner, 1985)
SML (Milner et al., 1990)
Todos han estado influenciados por MIRANDA. Cabe destacar
ORWELL (Wadler, 1985). Recoge y amplı́a muchos conceptos
introducidos por MIRANDA.
“Introduction to Functional Programming” (Bird y Wadler,
1988)
HASKELL
HASKELL frente a otros lenguajes de orden superior
Haskell es un estándar en la comunidad educativa hoy dia y en la
enseñanza de la Programación Funcional
Haskell B. Curry
Reune las principales caracterı́sticas de la PF moderna. De ahı́
que se defina un estándar, Haskell 98 (Peyton Jones, 2003;
Hudak y Fasel, 1999)
Actualmente se diseñan gran cantidad de bibliotecas gráficas,
de cálculo numérico, de acceso a BD, servidores web e
interconexión con otros lenguajes
Existencia de intérpretes y compiladores eficientes y de libre
disposición. GOFER (Mark Jones, 1992)
HUGS 98 (Jones, 1998) presenta caracterı́sticas adicionales,
como ampliación del sistema de tipos y librerı́a de funciones
gráficas
Funciones
Funciones
Una función f es una correspondencia entre dos conjuntos inicial
y final
f:A→B
f(x) 7−→ . . .
Ejemplos:
sucesor, sumaCuadrados (2 argumentos) y pi (constante)
sumacuadrados : ZxZ → Z
sumacuadrados(x, y) 7→ x2 + y2
Interesa evaluar la función para ciertos valores: ”El resultado de
aplicar la función f al valor x es y ”
Programas/Funciones
Programar es dar al ordenador los pasos para resolver un
problema
La solución se calcula a partir de los datos, luego un programa
se describe mediante funciones
Programación funcional: ordenador = evaluador
Prelude
Ejemplos
Prelude > 1 + 2
3 :: Integer
Prelude > cos (2 * pi)
1.0 :: Double
Prelude > [1..5]
[1, 2, 3, 4, 5] :: [Integer]
Prelude > mod 10 3
1 :: Integer
Prelude > mod 10 (3 + 1)
2 :: Integer
Reducción de Expresiones
Reducción I
El evaluador simplifica la expresión y muestra el resultado
cuadrado :: Integer → Integer
cuadrado x = x ∗ x
Simplificación en varios pasos de reducción
2 + cuadrado3
=⇒ ! por la definición de cuadrado
2+3∗3
=⇒ ! por el operador (∗)
2+9
=⇒ ! por el operador (+)
11
Reducción II
El evaluador simplifica la expresión y muestra el resultado
Simplificación en varios pasos de reducción
Un redex es cada parte de la expresión que pueda reducirse
Forma normal
Evaluador: mientras quede algún redex, reducir; cuando
alcance la forma normal, mostrar el resultado
Pero, ¿Qué ocurre si hay más de un redex?
Ejemplo
Reducción desde dentro
cuadrado(cuadrado3 )
=⇒ ! por la definición de cuadrado
cuadrado(3 ∗ 3)
=⇒ ! por el operador (∗)
cuadrado 9
=⇒ ! por la definición de cuadrado
9∗9
=⇒ ! por el operador (∗)
81
Reducción desde fuera
cuadrado(cuadrado3 )
=⇒ ! por la definición de cuadrado
(cuadrado 3) ∗ (cuadrado 3)
=⇒ ! por la definición de cuadrado
(3 ∗ 3) ∗ (cuadrado 3)
=⇒ ! por el operador (∗)
9 ∗ (cuadrado 3)
=⇒ ! por la definición de cuadrado
9 ∗ (3 ∗ 3)
=⇒ ! por el operador (∗)
9∗9
=⇒ ! por el operador (∗)
81
Funciones estrictas y transparecia referencial
Las funciones que para ser evaluadas necesitan que sus
parámetros estén en forma normal se llaman estrictas.
Ejs.: ∗ es estricto. cuadrado no es estricto.
Sea cual sea el orden de reducción, el resultado final es el
mismo. La reducción cambia la forma de una expresión, no su
valor
La transparencia referencial establece que una misma
expresión denota siempre el mismo valor
Si aparecen varios redexes, podemos elegir cualquiera sin que el
resultado varı́e. Pero la elección del redex equivocado puede no
conducir a la forma normal
Ejemplo
infinito :: Integer
cero :: Integer =⇒ Integer
infinito = 1 + infinito cero x = 0
Reducción desde dentro
Reducción desde fuera
cero infinito
cero infinito
=⇒ ! por la definición de infinito =⇒ ! por la definición de cero
cero (1 + infinito)
0
=⇒ ! por la definición de infinito
cero(1 + (1 + infinito))
=⇒ ! por la definición de infinito
...
La estrategia utilizada para seleccionar el redex es crucial
Un orden de reducción es una estrategia que indica qué redex
hay que seleccionar en cada paso de reducción
Orden de reducción aplicativo
Seleccionar siempre el redex más interno y más a la izquierda
Paso de parámetros por valor (call by value)
Evaluadores estrictos o impacientes
Problema: A veces se efectúan reducciones innecesarias
cero(10 ∗ 4)
=⇒ ! por el operador (∗)
cero 40
=⇒ ! por la definición de cero
0
cero infinito
Orden de reducción normal
Seleccionar siempre el redex más externo y más a la izquierda
Paso de parámetros por nombre (call by name)
Evaluadores no estrictos
Es normalizante
Problema: Ciertas expresiones se reducen varias veces
Ejemplo:
cuadrado(cuadrado3 )
Evaluación perezosa
Orden normal (paso por nombre): expresiones se reducen
varias veces
Solución: Evaluación perezosa (call by need)
Consiste en utilizar paso por nombre y recordar los valores de
los argumentos ya calculados para evitar recálculo
No se utilizan más reducciones que con paso por valor, luego
no es menos eficiente que ella y tiene las ventajas de paso por
nombre.
Haskell utiliza un evaluador perezoso
Evaluación perezosa: Ejemplo
cuadrado(cuadrado3 )
=⇒ ! por la definición de cuadrado
a ∗ a donde a = cuadrado3
=⇒ ! por la definición de cuadrado
a ∗ a donde a = b ∗ b donde b = 3
=⇒ ! por el operador (∗)
a ∗ a donde a = 9
=⇒ ! por el operador (∗)
81
Representación perezosa de la función cuadrado
Reducción perezosa de la función cuadrado
El Lenguaje Haskell
Caracterı́sticas
Haskell es un lenguaje funcional puro, no estricto y fuertemente
tipificado.
Puro: Transparencia referencial. Una expresión denota siempre
el mismo valor, en cualquier punto del programa en que
aparezca. Razonamiento ecuacional utilizado en matemáticas.
No estricto: orden no aplicativo. Evaluación perezosa:
Normalizante
Trabajo mı́nimo
Eficiente
Trabajo con estructuras de datos infinitas
Tipificación fuerte: elementos clasificados en categorı́as.
Sistema de tipos estático: comprobación en la compilación
Sistema de tipos polimórfico: mas flexible
Permite la sobrecarga: el mismo nombre
Son aconsejables las anotaciones de tipo en los programas
Sesiones con Haskell
Un programa Haskell consiste en una o varias definiciones de
funciones
Declaración: tipo
Definición: método de cómputo
Ejemplo:
-- Un ejemplo de fichero Haskell
-- Calcula el siguiente entero al argumento
sucesor :: Integer -> Integer
sucesor x = x + 1
-- Calcula la suma de los cuadrados de sus argumentos
sumaCuadrados :: Integer -> Integer -> Integer
sumaCuadrados x y = x * x + y * y
Sesiones con Haskell
Haskell es un lenguaje fuertemente tipificado. El conjunto
de valores, funciones y operadores predefinidos es ampliable,
incluso se pueden definir nuevos tipos de datos
sucesor :: Integer → Integer
sucesor(x) = x + 1
Declaración de tipo, ecuación, método de cómputo, parámetro
formal de la función
Una función de dos argumentos
sumaCuadrados :: Integer → Integer → Integer
sumaCuadrados x y = x ∗ x + y ∗ y
Main > sumaCuadrados (2 + 2) 3
25 :: Integer
Descargar