1 / 38

Entrada/Salida en el lenguaje funcional Haskell

Entrada/Salida en el lenguaje funcional Haskell. Carlos Caballero González. Contenido. El problema de la E/S en Haskell El tipo IO Operaciones Básicas Ejemplos El tipo IOError (Capturar excepciones) Ejemplo. Contenido. Graphical User Interface (GUI) Clasificación (High-medium-low)

hova
Download Presentation

Entrada/Salida en el lenguaje funcional Haskell

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Entrada/Salida en el lenguaje funcional Haskell Carlos Caballero González

  2. Contenido • El problema de la E/S en Haskell • El tipo IO • Operaciones Básicas • Ejemplos • El tipo IOError (Capturar excepciones) • Ejemplo Programación Declarativa Avanzada

  3. Contenido • Graphical User Interface (GUI) • Clasificación (High-medium-low) • Ejemplos FudGets • Ejemplos WxHaskell • Comparación de Código con JAVA • Referencias • Conclusión Personal Programación Declarativa Avanzada

  4. El problema de la E/S en Haskell • Haskell es un lenguaje funcional puro la integración de las operaciones de entrada y salida podría hacer perder la transparencia referencial del lenguaje • Supongamos que queremos leer un Entero desde el teclado • leerEntero :: Entero • Para todo n Entero se cumple que n + n = 2n • Pero la función leerEntero no cumpliría esta condición pues: leerEntero + leerEntero != 2* leerEntero Programación Declarativa Avanzada

  5. El tipo IO • La solución que aporta Haskell es tener un tipo específico para realizar las operaciones de Entrada Salida, este tipo es IO() • Es una mónada • Estructura de dato que encapsula una acción putChar :: IO Char getChar :: Char -> IO () Programación Declarativa Avanzada

  6. El tipo IO • El tipo IO a indica una acción de Entrada/Salida que devuelve un valor de tipo a • Hemos puesto IO a. • ¿Por qué no ponemos solamente IO?. • Porque toda acción debe devolver como resultado un dato concreto, y este dato también tendrá un tipo. • Cuando es un dato sin valor útil, su tipo será vacío (). Por lo tanto, además de IO (que representa una acción), aparecerá el tipo de dato concreto que devuelve dicha acción. Programación Declarativa Avanzada

  7. Operaciones Básicas. • Todas las funciones que se describen a continuación se encuentran en el módulo Prelude. No es necesario importar ninguna librería para poder utilizarlas. • Funciones de Entrada. • Son funciones que obtienen los datos del puerto de entrada estándar, normalmente el teclado del terminal de usuario. • Funciones de Salida. • Funciones que escriben los datos en el puerto de salida estándar, normalmente el monitor del terminal de usuario. Programación Declarativa Avanzada

  8. Operaciones Básicas. Entrada getChar::IO Char Recibe: nada. Acción: lee un carácter. Devuelve: el carácter leído. Ejemplo: • Prelude> getChar • a • Prelude> Programación Declarativa Avanzada

  9. Operaciones Básicas. Entrada getLine::IO String Recibe: nada. Acción: lee unalínea ( \n ). Devuelve: un string. • Ejemplo: • Prelude> getLine • Caspita • Prelude> Programación Declarativa Avanzada

  10. Operaciones Básicas. Entrada getContents::IO String Recibe: nada. Acción: lee unalínea ( \n ). Devuelve: un string. Hace lo mismo que getLine pero utilizando evaluación perezosa. Coge los caracteres uno a uno según se van necesitando. Programación Declarativa Avanzada

  11. Operaciones Básicas. Entrada • interact:: ( String -> String ) -> IO () • Se basa en la primitiva getContents para leer y en putStr para escribir. • Recibe: una función de tipo String -> String. • Acción: lee un String del puerto de entrada, lo pasa a la función y el String resultado lo escribe en el puerto de salida. • Devuelve: nada. • Ejemplo: • import Char • main = interact (map toUpper) • Convierte la entrada del usuario a mayúsculas. Programación Declarativa Avanzada

  12. Operaciones Básicas. Salida putChar::Char -> IO () Primitiva. Recibe: un carácter. Acción: escribe el carácter recibido. Devuelve: nada. Ejemplo: • Main> putChar 'a' • a • Main> Programación Declarativa Avanzada

  13. Operaciones Básicas. Salida putStr::String -> IO () Se basa en la primitiva putChar. Recibe: un String. Acción: escribe el String recibido. Utiliza putChar para escribir los caracteres de uno en uno. Devuelve: nada. Ejemplo: • Main> putStr "puñetas" • puñetas Programación Declarativa Avanzada

  14. Operaciones Básicas. Salida putStrLn::String -> IO () Recibe: un String. Acción: escribe el String recibido. Utiliza putStr, añadiendo un carácter de “nueva línea” Devuelve: nada. Ejemplo: • Main> putStrLn "puñetas" • Puñetas • Main> Programación Declarativa Avanzada

  15. Operaciones Básicas. Ficheros • Funciones que actúan sobre ficheros de caracteres. • type FilePath = String • Una forma de nombrar los ficheros. Es un String que contiene la ruta del fichero. • Internamente utiliza algún método específico de implementación para convertir cadenas en identificadores de fichero válidos para el sistema. Programación Declarativa Avanzada

  16. Operaciones Básicas. Ficheros • readFile::FilePath -> IO String • Recibe: un nombre de fichero. • Acción: lee el fichero indicado. • Devuelve: un String con el contenido del fichero. • El fichero se lee según se necesita, de forma “perezosa”. En este sentido funciona igual que la función getContents. • Ejemplo. • readFile "c:/PDA/fentrada"          Programación Declarativa Avanzada

  17. Operaciones Básicas. Ficheros • writeFile::FilePath -> String -> IO () • Recibe: un nombre de fichero y un String. • Acción: escribe el String recibido como segundo argumento en el fichero indicado. Presupone que existe y borra su contenido antes de escribir. • Devuelve: nada. • Para escribir un valor que no sea de tipo String, debe convertirse previamente con la función show. • Ejemplo. • writeFile "C:/PDA/CUADRADO" (show [ (x,x*x) | x <- [1,2..100] ] • Escribe en el fichero cuadrado el par formado por los 100 primeros números y sus cuadrados. Programación Declarativa Avanzada

  18. Operaciones Básicas. Ficheros • appendFile::FilePath -> String -> IO () • Lo mismo que writeFile pero añade el String al final del fichero, manteniendo el contenido anterior. • Ejemplo. • appendFile "C:/PDA/CUADRADO" (show [ (x,x*x) | x <- [1,2..100] ] ) Programación Declarativa Avanzada

  19. Operaciones Básicas • return::a-> IO a • Se emplea para convertir un valor en una acción, puede ser interpretada como la identidad. • Ejemplo: • return x • x • do • Las acciones se ejecutan secuencialmente • El ámbito de una variable introducida por <- son las acciones posteriores hasta el final de la expresión do • El tipo de la expresión do es el tipo de la última acción • La regla del sangrado de Haskell se aplica tras la palabra do, por lo que todas las acciones de su ámbito deben estar en la misma columna Programación Declarativa Avanzada

  20. Operaciones Básicas • Ejemplo de empleo de do • miAcción :: IO() • miAcción = do putStr “Dame un texto: ” • xs <- getLine • putStr “En mayúsuclas es: “ • putStr (map toUpper xs) • Main> miAcción • Dame un texto: puñetas • En mayúsuclas es: PUÑETAS Programación Declarativa Avanzada

  21. Tipo IOError () • Ejemplo: • muestraFichero :: IO() • muestraFichero = do putStr “Introduce nombre del fichero: ” • nombre <- getLine • contenido <- readFile nombre • putStr contenido • ¡¿Qué sucede si el fichero no existe?! • Como cualquier lenguaje de programación Haskell debe proporcionarnos mecanismos para controlar los posibles errores, en el caso de Entrada/Salida Haskell proporciona el tipo IOError() Programación Declarativa Avanzada

  22. El tipo IOError() • Las excepciones pueden ser tratadas mediante la función catch • Catch :: IO a -> (IOError -> IO a) -> IO a • Primer Argumento: La acción a realizar • Segundo Argumento: La acción en caso de excepción • Ejemplo: • muestraFichero’ :: IO() • muestraFichero’ = muestraFichero ‘catch’ manejador • Where • manejador err = • do putStr (“Se produjo un error” ++ show err ++ “\n”) • muestraFichero’ Programación Declarativa Avanzada

  23. Graphical User Interface (GUI) • Existe un gran número de bibliotecas para generar GUI en Haskell. • Desgraciadamente no hay ningún estándar (todas tienen ventajas y deficiencias respecto a otras) • Son independientes al núcleo de Haskell (debido a que no existe el estándar) • Normalmente estas bibliotecas se han clasificado como low-level, medium-level y High-level Programación Declarativa Avanzada

  24. Graphical User Interface (GUI) • Low-Level. Se obtienen buenos resultados pero son de demasiado bajo nivel. • HOpenGL (sólo gráficos) • TclHaskell • High-Level. Actualmente son experimentales en muchos sentidos, pero se empiezan a obtener buenos resultados. • wxHaskell (veremos ejemplos) • Gtk2HS • HGL (Sólo gráficos) • Object I/O • Medium-level. Como todo en muchos problemas hay que llegar a un consenso. • FrankTK • Fudgets (veremos ejemplos) • Fruits/wxFruits • Haggis Programación Declarativa Avanzada

  25. Graphical User Interface (GUI) • ¿Por qué elegir trabajar con Haskell + GUI ? • El programador se encuentra igual de cómodo trabajando en el desarrollo de GUI’s con Haskell que con cualquier otro lenguaje • TODAS las bibliotecas tienen un API bastante aclaratorio y fácil de comprender (como JAVA) • Se poseen características propias de un lenguaje declarativo que no se posee en otros lenguajes como: • Programación perezosa y estructuras infinitas • Funciones de orden superior • Un potente sistema de clases de tipos Programación Declarativa Avanzada

  26. Graphical User Interface (GUI)FudGets • FudGets es una biblioteca de GUI’s para el lenguaje funcional Haskell. • El trabajo principal de esta biblioteca fue desarrollada durante 1991-1996 aunque aún se esta manteniendo la biblioteca. • Fue desarrollada por Thomas Hallgren y Magnus Carlsson. Programación Declarativa Avanzada

  27. Graphical User Interface (GUI)FudGets • Algunas Imágenes de lo que se puede lograr: Programación Declarativa Avanzada

  28. Graphical User Interface (GUI)FudGets • Primer Código. ¡Hola Mundo! • import Fudgets main = fudlogue (shellF "Hello" (labelF "Hello, world!")) • import Fudgets main = fudlogue (shellF "Hello" (labelF "Hello, world!" >+< quitButtonF)) Programación Declarativa Avanzada

  29. Graphical User Interface (GUI)FudGets import Fudgets main = fudlogue (shellF "Pocket Calculator" calcF) calcF = intDispF >==< mapstateF calc [0] >==< buttonsF data Buttons = Plus | Minus | Times | Div | Enter | Digit Int deriving (Eq) buttonsF = placerF (matrixP 4) ( listF [d 7, d 8, d 9,op Div, d 4, d 5, d 6,op Times, d 1, d 2, d 3,op Minus, hole,d 0,ent, op Plus]) where d n = (Digit n,buttonF (show n)) ent = op Enter hole = (Enter,holeF) op o = (o,buttonF (opLabel o)) where opLabel Plus = "+" opLabel Minus = "-“ opLabel Times = "*“ opLabel Div = "/“ opLabel Enter = "Ent" calc (n:s) (Digit d,_) = new (n*10+d) s calc s (Enter,_) = (0:s,[]) calc (y:x:s) (Plus,_) = new (x+y) s calc (y:x:s) (Minus,_) = new (x-y) s calc (y:x:s) (Times,_) = new (x*y) s calc (y:x:s) (Div,_) = new (x `div` y) s calc s _ = (s,[]) new n s = (n:s,[n]) Programación Declarativa Avanzada

  30. Graphical User Interface (GUI)WxHaskell • wxHaskell es una biblioteca de GUI’s para el lenguaje Haskell • Comenzó a desarrollarse en 1992 • Se encuentra entre los 25 proyectos más activos de código abierto. Programación Declarativa Avanzada

  31. Graphical User Interface (GUI)WxHaskell • Algunas imágenes que se pueden lograr: Programación Declarativa Avanzada

  32. Graphical User Interface (GUI)WxHaskell import Graphics.UI.WX main :: IO () main = start hello hello :: IO () hello = do f <- frame [text := "Hello world!", clientSize := sz 300 200] file <- menuPane [text := "&File"] quit <- menuQuit file [help := "Quit the demo", on command := close f] hlp <- menuHelp [] about <- menuAbout hlp [help := "About wxHaskell"] status <- statusField [text := "Welcome to wxHaskell"] set f [ statusBar := [status] , menuBar := [file,hlp] ,on (menu about) := infoDialog f "About wxHaskell""This is a wxHaskell demo" ] Programación Declarativa Avanzada

  33. Graphical User Interface (GUI)WxHaskell import Graphics.UI.WX import Graphics.UI.WXCore main = start $ do f <- frame [text := "Custom color box controls"] c <- colorBox f [boxcolor := red] set f [layout := floatCenter $ widget c ,clientSize := sz 280 100] type ColorBox a = Window (CColorBox a) data CColorBox a = CColorBox colorBox :: Window a -> [Prop (ColorBox ())] -> IO (ColorBox ()) colorBox parent props = do let defaults = [clientSize := sz 20 20, border := BorderStatic] cboxprops = castProps cast props w <- window parent (defaults ++ cboxprops) let cbox = cast w set cbox [on click := selectColor cbox] return cbox where selectColor cbox pt = do c <- get cbox boxcolor mbc <- colorDialog cbox c case mbc of Just c -> set cbox [boxcolor := c] Nothing -> return () cast :: Window a -> ColorBox () cast = objectCast boxcolor :: Attr (ColorBox a) Color boxcolor = newAttr "boxcolor" getter setter where getter cbox = get cbox bgcolor setter cbox clr = do set cbox [bgcolor := clr] refresh cbox Programación Declarativa Avanzada

  34. Graphical User Interface (GUI)JAVA • El simple “Hola Mundo” de 3 lineas en cualquiera de las bibliotecas de GUI’s de JAVA se convierte en una labor más tediosa import javax.swing.*; import java.awt.*; import java.awt.event.*; public class HolaMundoSwing { public static void main(String[] args) { JFrame frame = new JFrame("HolaMundoSwing"); final JLabel label = new JLabel("Hola Mundo"); frame.getContentPane().add(label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.addWindowListener(new java.awt.event.WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } } ); frame.pack(); frame.setVisible(true); } } Programación Declarativa Avanzada

  35. Graphical User Interface (GUI)JAVA public class HolaMundoSwing { public static void main(String[] args) { JFrame frame = new JFrame("HolaMundoSwing"); ... frame.pack(); frame.setVisible(true); } } Programación Declarativa Avanzada

  36. Referencias • Razonando con Haskell. Un curso sobre programación funcional. Blas C. Ruiz, Fco. Gutiérrez, Pablo Guerrero, José E. Gallardo (2004) • A Gentle introduction to Haskell. P. Hudak, J. Fasel (1999) • Entrada / Salida en Haskell (http://www.info-ab.uclm.es/asignaturas/42630/BuzAPD/Trabajos/IOHaskell.doc) • Introducción al lenguaje Haskell. (http://lsi.uniovi.es/~labra/FTP/IntHaskell98.pdf) Jose E. Labra G. (1998) • IO in Haskell. Using stream- and monad-IO in Haskell. Oskar OjalaHelsinki University of Technology Programación Declarativa Avanzada

  37. Referencias • Haskell.org (http://haskell.org) • wxHaskell (http://wxhaskell.sourceforge.net/) • FudGets (http://www.md.chalmers.se/Cs/Research/Functional/Fudgets/) Programación Declarativa Avanzada

  38. Conclusión Personal • En Haskell se puede desarrollar exactamente lo mismo que se puede desarrollar en cualquier lenguaje actual con capacidad de desarrollo de GUI’s • El desarrollo de las GUI’s en Haskell son incluso más simples que en cualquier otro lenguaje • Se dispone de las características de un lenguaje declarativo (Programación perezosa y estructuras infinitas, funciones de orden Superior, potente sistema de clases de tipos) • Es una verdadera desgracia que no se haya equipado de un estándar para poder realizar GUI’s en Haskell potenciaría de una gran manera el desarrollo de las mismas, no dejandolas de las manos de particulares Programación Declarativa Avanzada

More Related