Title: Entrada/Salida en el lenguaje funcional Haskell
1Entrada/Salida en el lenguaje funcional Haskell
- Carlos Caballero González
2Contenido
- El problema de la E/S en Haskell
- El tipo IO
- Operaciones Básicas
- Ejemplos
- El tipo IOError (Capturar excepciones)
- Ejemplo
3Contenido
- Graphical User Interface (GUI)
- Clasificación (High-medium-low)
- Ejemplos FudGets
- Ejemplos WxHaskell
- Comparación de Código con JAVA
- Referencias
- Conclusión Personal
4El 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
5El 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 -gt IO ()
6El 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.
7Operaciones 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. -
8Operaciones Básicas. Entrada
- getCharIO Char
- Recibe nada.
- Acción lee un carácter.
- Devuelve el carácter leído.
- Ejemplo
- Preludegt getChar
- a
- Preludegt
9Operaciones Básicas. Entrada
- getLineIO String
- Recibe nada.
- Acción lee una línea ( \n ).
- Devuelve un string.
- Ejemplo
- Preludegt getLine
- Caspita
- Preludegt
10Operaciones Básicas. Entrada
- getContentsIO String
- Recibe nada.
- Acción lee una lí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.
11Operaciones Básicas. Entrada
- interact ( String -gt String ) -gt IO ()
-
- Se basa en la primitiva getContents para leer y
en putStr para escribir. - Recibe una función de tipo String -gt 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.
12Operaciones Básicas. Salida
- putCharChar -gt IO ()
- Primitiva.
- Recibe un carácter.
- Acción escribe el carácter recibido.
- Devuelve nada.
- Ejemplo
- Maingt putChar 'a'
- a
- Maingt
13Operaciones Básicas. Salida
- putStr String -gt 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
- Maingt putStr "puñetas"
- puñetas
14Operaciones Básicas. Salida
- putStrLnString -gt IO ()
- Recibe un String.
- Acción escribe el String recibido. Utiliza
putStr, añadiendo un carácter de nueva línea - Devuelve nada.
- Ejemplo
- Maingt putStrLn "puñetas"
- Puñetas
- Maingt
15Operaciones 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.
16Operaciones Básicas. Ficheros
- readFileFilePath -gt 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"
17Operaciones Básicas. Ficheros
- writeFileFilePath -gt String -gt 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,xx) x
lt- 1,2..100 - Escribe en el fichero cuadrado el par formado por
los 100 primeros números y sus cuadrados.
18Operaciones Básicas. Ficheros
- appendFileFilePath -gt String -gt 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,xx) x
lt- 1,2..100 )
19Operaciones Básicas
- returna-gt 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 lt- 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
20Operaciones Básicas
- Ejemplo de empleo de do
- miAcción IO()
- miAcción do putStr Dame un texto
- xs lt- getLine
- putStr En mayúsuclas
es - putStr (map toUpper xs)
- Maingt miAcción
- Dame un texto puñetas
- En mayúsuclas es PUÑETAS
21Tipo IOError ()
- Ejemplo
- muestraFichero IO()
- muestraFichero do putStr Introduce nombre del
fichero - nombre lt-
getLine - contenido lt-
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()
22El tipo IOError()
- Las excepciones pueden ser tratadas mediante la
función catch - Catch IO a -gt (IOError -gt IO a) -gt 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
23Graphical 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
24Graphical 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
25Graphical User Interface (GUI)
- Por qué elegir trabajar con Haskell GUI ?
- El programador se encuentra igual de cómodo
trabajando en el desarrollo de GUIs 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
26Graphical User Interface (GUI)FudGets
- FudGets es una biblioteca de GUIs 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.
27Graphical User Interface (GUI)FudGets
- Algunas Imágenes de lo que se puede lograr
28Graphical 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!" gtlt quitButtonF))
29Graphical User Interface (GUI)FudGets
- import Fudgets
- main fudlogue (shellF "Pocket Calculator"
calcF) - calcF intDispF gtlt mapstateF calc 0 gtlt
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"
30Graphical User Interface (GUI)WxHaskell
- wxHaskell es una biblioteca de GUIs para el
lenguaje Haskell - Comenzó a desarrollarse en 1992
- Se encuentra entre los 25 proyectos más activos
de código abierto.
31Graphical User Interface (GUI)WxHaskell
- Algunas imágenes que se pueden lograr
32Graphical User Interface (GUI)WxHaskell
- import Graphics.UI.WX
- main IO ()
- main start hello
- hello IO ()
- hello do
- f lt- frame text "Hello world!",
clientSize sz 300 200 - file lt- menuPane text "File"
- quit lt- menuQuit file help "Quit the
demo", on command close f - hlp lt- menuHelp
- about lt- menuAbout hlp help "About
wxHaskell" - status lt- statusField text "Welcome to
wxHaskell" - set f statusBar status , menuBar
file,hlp ,on (menu about)
infoDialog f "About wxHaskell" "This is a
wxHaskell demo"
33Graphical User Interface (GUI)WxHaskell
- import Graphics.UI.WX
- import Graphics.UI.WXCore
- main start
- do f lt- frame text "Custom color box
controls" - c lt- 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 -gt Prop (ColorBox ()) -gt
IO (ColorBox ()) - colorBox parent props
- do let defaults clientSize sz 20 20,
border BorderStatic - cboxprops castProps cast props
- w lt- window parent (defaults
cboxprops) - let cbox cast w
- set cbox on click selectColor
cbox - return cbox
- where
- selectColor cbox pt
- do c lt- get cbox boxcolor
34Graphical User Interface (GUI)JAVA
- El simple Hola Mundo de 3 lineas en cualquiera
de las bibliotecas de GUIs 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_CLOS
E) frame.addWindowListener(new
java.awt.event.WindowAdapter() - public void windowClosing(WindowEvent e)
- System.exit(0)
-
- )
- frame.pack()
- frame.setVisible(true)
-
-
35Graphical User Interface (GUI)JAVA
- public class HolaMundoSwing
- public static void main(String args)
- JFrame frame new JFrame("HolaMundoSwing")
- ...
- frame.pack()
- frame.setVisible(true)
-
-
36Referencias
- 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/Buz
APD/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 Ojala Helsinki University of Technology
37Referencias
- Haskell.org (http//haskell.org)
- wxHaskell (http//wxhaskell.sourceforge.net/)
- FudGets (http//www.md.chalmers.se/Cs/Research/Fun
ctional/Fudgets/)
38Conclusión Personal
- En Haskell se puede desarrollar exactamente lo
mismo que se puede desarrollar en cualquier
lenguaje actual con capacidad de desarrollo de
GUIs - El desarrollo de las GUIs 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 GUIs
en Haskell potenciaría de una gran manera el
desarrollo de las mismas, no dejandolas de las
manos de particulares