Práctica 1. Programación Funcional Introducción a Helium Who? Lenguajes y Paradigmas de Programación
Objetivo de la práctica Presentar las facilidades básicas del entorno de programación Helium Presentar los conceptos básicos en cuanto a sintaxis de Haskell Familiarizarse con la recursión en la programación funcional
Helium Principales diferencias de Helium con el estándar Haskell98 regla de sangrado sistema de módulos sintaxis de partes izquierdas no se soportan clases no se permite sobrecarga de operadores menos librerías
Helium entorno gráfico Hint editor de textos ConTEXT se pueden lanzar órdenes desde los menús uso de comandos estándar de Haskell
Helium Comandos básicos LIST OF COMMANDS: Any command may be abbreviated to :c where c is the first character in the full name. :load <modulename> :reload :type <expression> :info <function> :edit [<row:col>] :jump :quit :help :clear - loads the specified module - reloads the current module - print type of the expressi - view function in on-line d - edit the currenty loaded m - jump editor to last error - exit the interpreter - shows available commands - clears the screen
Edición y carga de programas Un programa Haskell es un conjunto de módulos. Cada módulo se especifica en un fichero y contendrá una serie de funciones. El nombre del módulo debe empezar por mayúscula El nombre del módulo debe coincidir con el nombre del fichero donde se almacena Los módulos empiezan con las palabras clave: module NombreModulo where y a continuación las definiciones de tipos y código de las funciones del módulo
Indentación Las declaraciones de más alto nivel (definiciones de funciones) se indentan en la primera columna. El inicio de la siguiente definición de función en la primera columna establece el fin de la declaración anterior. Para continuar una expresión en la siguiente fila, se indentará a un nivel más.
Comentarios y más Comentarios comentario de una línea: - - al principio de la línea comentario de un bloque de varias líneas: {- al principio del bloque y -} al final
Comentarios y más Comentarios comentario de una línea: - - al principio de la línea comentario de un bloque de varias líneas: {- al principio del bloque y -} al final Escape el caracter de escape en Haskell es el \
Cada componente de un programa es una función Las funciones devuelven siempre un único resultado si queremos devolver varias cosas, tendremos que usar tuplas (, ) Existen funciones predefinidas Haskell es un lenguaje funcional lazy
Cada componente de un programa es una función Las funciones devuelven siempre un único resultado si queremos devolver varias cosas, tendremos que usar tuplas (, ) Existen funciones predefinidas Haskell es un lenguaje funcional lazy Definición de funciónes 1 Definiremos su tipo 2 Definiremos su comportamiento
Definición de funciones Ejemplo increment :: Int -> Int increment x = x + 1
Definición de funciones Ejemplo increment :: Int -> Int increment x = x + 1 Ejemplo roots :: Float -> Float -> Float -> (Float, Float)
Tipos y operadores definidos Bool True, False Int -100, 1, 2,... Integer -3333333333, 3, 484398473,... Float/Double -3.22425, 0.0, 3.0,... Char a, z, ;,... String Hola, Funcion,... == /= < <= > >=
Ejercicio Escribir en el editor de textos el siguiente programa: module Hello where hello n = concat (replicate n hello ) cargar el programa en el intérprete corregir el error que aparece introducir la declaración de tipos
Información sobre tipos module Errortipos where main = f 0 a f :: Char -> Int -> String f c i = [c] ++ showint i Cargar el programa anterior y observar la respuesta del sistema
Información sobre tipos Compiling Errortipos.hs (3,10): Type error in application expression : f 0 a term : f type : Char -> Int -> String does not match: Int -> Char -> a probable fix : re-order arguments
Expresión condicional if-then-else El tipo de datos Bool define los valores True y False if cond then result1 else result2 Se pueden usar operadores booleanos como &&,, o not
Guardas (ecuación condicional) Esquema de guardas Las guardas nos permiten programar usando una estrategia similar al pattern matching. Tendremos una única definición de función pero mediante las guardas podemos distinguir los distintos casos posibles. nombrefunc argts cond = result1 cond = result2. otherwise = resultn
Ejemplo (1/2) module Power1 where power1 :: Int -> Int -> Int power1 _ 0 = 1 power1 n t = n * power1 n (t-1)
Ejemplo (2/2) module Power2 where power2 :: Int -> Int -> Int power2 _ 0 = 1 power2 n t even t = power2 (n*n) (div t 2) otherwise = n * power2 (n*n) (div t 2)
De función a operador y viceverse funciones infijas operadores prefijos Normalmente los operadores se invocan de forma infija y las funciones de forma prefija. Para poder invocar una función de forma infija debemos encerrarla entre backquotes (acentos graves) 5 ` max ` 3 Para poder invocar un operador de forma prefija debemos encerrarlo entre paréntesis (+) 5 3
De función a operador y viceverse funciones infijas operadores prefijos Normalmente los operadores se invocan de forma infija y las funciones de forma prefija. Para poder invocar una función de forma infija debemos encerrarla entre backquotes (acentos graves) 5 ` max ` 3 Para poder invocar un operador de forma prefija debemos encerrarlo entre paréntesis (+) 5 3
De función a operador y viceverse funciones infijas operadores prefijos Normalmente los operadores se invocan de forma infija y las funciones de forma prefija. Para poder invocar una función de forma infija debemos encerrarla entre backquotes (acentos graves) 5 ` max ` 3 Para poder invocar un operador de forma prefija debemos encerrarlo entre paréntesis (+) 5 3
Recursión Normalmente nos encontraremos con dos esquemas de recursión básicos: cuando hagamos recursión sobre enteros el caso base será normalmente el valor 0 (ó 1) el caso de inducción será el sucesor al valor actual
Ejercicios Leed el boletín de la práctica 1. Realizad los ejercicios que se proponen al final del mismo.