Está en la página 1de 8

Cap tulo 1.

Programacin Funcional o

Programacin funcional o Funciones


f :A B f (x) . . . Ejemplos: sucesor, sumaCuadrados (2 argumentos) y pi (constante) sucesor : Z Z sucesor(x) x + 1 sumaCuadrados : Z Z Z sumaCuadrados(x, y) x2 + y 2 : R 3.1415927 . . .

Evaluacin de una funcin para ciertos valores de la variable: o o sucesor(1) = 2 sumaCuadrados(2, 3) = 13

Cap tulo 1. Programacin Funcional o

Sesiones y declaraciones
Programar = especicar los pasos para resolver un problema. Solucin a un problema = valor calculado a o partir de ciertos datos. En programacin funcional, ordenador = calcuo ladora o evaluador Existen un conjunto de funciones predenidas (Prelude)
Prelude> 1 + 2 3 :: Integer

Prelude> [1..5] [1, 2, 3, 4, 5] :: [Integer ] Prelude> sum [1..10] 55 :: Integer

El siguiente ejemplo muestra cmo se usan o funciones de ms de un argumento: a


Prelude> mod 10 3 1 :: Integer Prelude> mod 10 (3 + 1) 2 :: Integer

Las l neas anteriores representan un dilogo con a el evaluador. El siguiente ejemplo utiliza valores reales:
Prelude> cos pi 1.0 :: Double

Slo se usan parntesis cuando es necesario: o e


Prelude> cos (2 pi ) 1.0 :: Double

Cap tulo 1. Programacin Funcional o

Haskell es un lenguaje fuertemente tipicado. Proporciona un rico conjunto de elementos predenidos. Este conjunto es ampliable v declaraciones o deniciones: a
sucesor :: Integer Integer declaracin de tipo o sucesor x = x + 1 cmo computar el valor de la funcin o o Main> sucesor 3 4 :: Integer Main> 10 sucesor 3 40 :: Integer

Las siguientes declaraciones muestra la denicin de una funcin de dos argumentos: o o


sumaCuadrados :: Integer Integer Integer sumaCuadrados x y = x x + y y Main> sumaCuadrados 2 3 13 :: Integer Main> sumaCuadrados (2 + 2) 3 25 :: Integer

Los tipos de los distintos argumentos aparecen separados por el constructor de tipo . El ultimo tipo es el del resultado.

Cap tulo 1. Programacin Funcional o

Reduccin de expresiones o
El evaluador simplica la expresin original too do lo posible y muestra el resultado. La simplicacin se produce, en general, tras o varios pasos:
cuadrado :: Integer Integer cuadrado x = x x

La labor del evaluador consiste en: mientras quede algn redex en la expresin u o seleccionar un redex y reducirlo Una vez alcanzada la forma normal, el evaluador muestra el resultado. Qu ocurre si hay ms de un redex?. e a Por ejemplo cuadrado (cuadrado 3)

podemos calcular el valor de la expresin: o


2 + = ! 2 + = ! 2 + = ! 11 cuadrado 3 por la denicin de cuadrado o (3 3) por el operador () 9 por el operador (+)

Cada paso es una reduccin. o Un redex es cada parte de la expresin que o pueda reducirse. Cuando una expresin no puede ser reducida o ms se dice que est en forma normal. a a

Cap tulo 1. Programacin Funcional o

Podemos reducir la expresin desde dentro hao cia fuera (primero los redexes internos):
cuadrado(cuadrado 3) = ! por la denicin de cuadrado o cuadrado(3 3) = ! por el operador () cuadrado 9 = ! por la denicin de cuadrado o 99 = ! por el operador () 81

= ! por la denicin de () o 9 (cuadrado 3) = ! por la denicin de cuadrado o 9 (3 3) = ! por el operador () 9 9 = ! por el operador () 81

Para reducir la expresin e1 e2 hay que reducir o previamente e1 y e2. ( es estricto).

Esta estrategia presenta algunos problemas. Una estrategia mejor consiste en reducir la expresin desde fuera hacia dentro (primero los reo dexes externos):
cuadrado x = x x

No es necesario evaluar previamente el argumento para aplicar la denicin de la funcin cuadrado. o o


cuadrado(cuadrado 3) = ! por la denicin de cuadrado o (cuadrado 3) (cuadrado 3) = ! por la denicin de cuadrado o (3 3) (cuadrado 3)

Cap tulo 1. Programacin Funcional o

Transparencia referencial
Sea cual sea la estrategia seguida en las reducciones, el resultado nal (el valor 81) es el mismo: Si aparecen varios redexes, podemos elegir cualquiera. Sin embargo, la reduccin de un redex equivoo cado puede que no conduzca a la forma normal de una expresin: o
innito innito cero cero x :: Integer = 1 + innito :: Integer Integer =0

cero innito = ! por denicin de cero o 0

n :: Integer cero n = 0. En particular, cero innito = 0. La estrategia utilizada para seleccionar el redex es crucial.

Si en cada momento elegimos el redex ms a interno:


cero innito = ! por denicin de innito o cero (1 + innito) = ! por denicin de innito o cero (1 + (1 + innito)) = ! por denicin de innito o ...

y la evaluacin no terminar nunca. o a Si en cada paso elegimos el redex ms externo: a

Cap tulo 1. Programacin Funcional o

Ordenes de reduccin aplicativo y normal o orden de reduccin = Estrategia que indica qu reo e dex hay que seleccionar en cada paso de la reduccin. o Existen varios rdenes de reduccin. Dos de los o o ms interesantes: a Orden aplicativo orden normal. Orden aplicativo: Seleccionar siempre el redex ms interno y ms a a a la izquierda. Esta estrategia de reduccin es conocida como o paso de parmetros por valor (call by value). a A los evaluadores que utilizan este orden se los llama estrictos o impacientes. Problemas del paso por valor A veces, se efectan reducciones que no son u necesarias:
cero (10 4) = ! por el operador () cero 40 = ! por denicin de cero o 0

Problema an mayor: puede no conducir a u la forma normal de la expresin. Por ejemplo: o cero innito Orden de reduccin normal o Consiste en seleccionar el redex ms externo y a ms a la izquierda. a Esta estrategia de reduccin se conoce como o paso de parmetros por nombre (call by name). a A los evaluadores que utilizan el orden normal se los llama no estrictos. El paso por nombre es normalizante

Cap tulo 1. Programacin Funcional o

Evaluacin perezosa o Con paso por nombre ciertas expresiones se reducen varias veces. En cuadrado (cuadrado 3) la expresin: o (3 3) es calculada 2 veces. Esto no ocurre en la reduccin que usa paso o por valor La estrategia de paso de parmetros por nea cesidad (call by need), tambin conocida como e evaluacin perezosa, soluciona este problema. o La evaluacin perezosa consiste en utilizar pao so por nombre y recordar los valores de los argumentos ya calculados para evitar recalcularlos:
cuadrado (cuadrado 3) = ! por la denicin de cuadrado o a a donde a = cuadrado 3 = ! por la denicin de cuadrado o a a donde a = b b donde b = 3 = ! por el operador () a a donde a = 9 = ! por el operador () 81

cuadrado x

- x 

cuadrado cuadrado 3

*
-cuadrado 3

* 81 = *
- 9  - 3