HSP(Haskell Server Pages)
Download
Report
Transcript HSP(Haskell Server Pages)
HSP(Haskell Server Pages)
Alejandro del Real Chicharro
José Emilio Villena Irigoyen
1
Índice
Introducción
La función page
La sintaxis de HSP
HJavaScript
HSP Foro Web
Conclusiones
Futuros Trabajos
Bibliografía
2
Introducción
No hace mucho tiempo, la World Wide Web estaba formada casi exclusivamente de
páginas estáticas. Hoy, sin embargo, el uso de páginas dinámicas en la Web se ha
incrementado hasta tal punto de necesitar mejores herramientas para la creación de
éstas.
Los programadores comienzan a usar algunos lenguajes script especializados que
permiten mezclar XML con código, p.e. PHP, ASP o también puedan usar CGI.
La mayoría de los lenguajes compartían los mismos defectos, y algunos hasta varios
de estos. Ellos modelaban texto HTML como texto sin formato, y esto violaba uno de
los principios de abstracción de Tennent.
3
Introducción
Se busca un lenguaje funcional que soporte un modelo de programación completo y la
facilidad de uso de un lenguaje script especializado, mientras aún mantenga el gran
potencial de XML.
En el 2000, Erik Meijer y Danny van Velzen presentaron lo que ellos llamaron como
‘Haskell Server Pages’ (HSP), un lenguaje de programación Web de dominio específico,
basado en la funcionalidad de la programación del lenguaje Haskell.
Introduciendo un nuevo tipo de datos data XML que garantizaba la correcta formación
de páginas dinámicas y una mejor integración de XML con otros códigos.
Permitir a los programadores usar fragmentos de sintaxis XML en código Haskell, y
viceversa, permitir embeber expresiones Haskell dentro de fragmentos XML.
4
Introducción
Código ASP:
Sacamos el bucle para hacer la
página más ordenada.
<TABLE border=”1”>
<% For x = 1 To 16 %>
<TR>
<% For y = 1 To 16 %>
<TD bicolor = <%= genColor(x,y) %>>
(<%= x %>,<%= y %>)
</TD>
<% Next %>
</TR>
<% Next %>
</TABLE>
5
Introducción
Código ASP:
<TABLE border=”1”>
<% For x = 1 To 16 %>
<TR>
<% Call GenData (x) %>
</TR>
<% Next %>
</TABLE>
El problema es que ASP
no permite esto.
Tendríamos que ejecutarlo dentro
de un módulo de Visual Basic.
<%
<% Sub
SubGenData(x)
GenData(x) %>
Foryy==11 To
To 16
<% For
16 %>
<TD>Response.Write “<TD bgcolor=“
Response.Write
genColor(x,y)
(<%= x %>,<%=
y %>)
Response.Write “>”
Response.Write “(“& x &”,” & y & “)”
</TD>
Response.Write “</TD>”
<% Next
Next %>
<% EndEnd
Sub%>
Sub
%>
6
Introducción
Código en Haskell:
table :: TABLE
Está todo más estructurado.
table =
<TABLE border=”1”>
<% mkRows cells %>
</TABLE>
cells ::[[(Int, Int)]]
cells =
[ [(x,y) | x [1..16] ]
| y [1..16]
]
mkRows:: [[(Int, Int)]] [TR]
mkRows = map $ \cs
<TR><% mkColumns cs %></TR>
mkColums :: [[(Int,Int)]] —>[TD]
mkColums = map $ \c
<TD bgcolor = (genColor c)>
$ Es una función asociativa por la
<% c %>
derecha para la eliminación de
</TD>
paréntesis
7
Introducción
A parte de las extensiones puramente sintácticas, HSP también facilita un
modelo de programación con tipos de datos, clases y funciones que ayuden
con algunas tareas de la programación Web.
Por ejemplo:
Mantener el estado de los usuarios en transacciones usando sesiones.
Mantener el estado de aplicaciones entre transacciones con diferentes
usuarios.
Acceder a consultas de datos y variables de entorno
8
La función page
Para generar una completa aplicación de páginas HSP, necesitamos definir la
función page. De forma análoga a la función main de Haskell.
la función page es llamada cuando una página HSP es requerida.
page = <HTML>
<HEAD>
<TITLE>¡Hola Mundo!</TITLE>
</HEAD>
</HTML>
9
La función page
Páginas XML y páginas Híbridas
Como un documento válido XML (o bien XHTML) es también una de las
fuentes principales de los programas HSP, necesitamos construir páginas que
nos permitan utilizar la potencia de XML junto con el lenguaje Haskell.
Por ejemplo un trozo de código en XML que muestra un reloj con la hora de
cuando un página fue pedida sería:
<HTML>
<HEAD><TITLE>Página XML</TITLE></HEAD>
<BODY>
<H1>¡Hola mundo!</H1>
<P>Página pedida con <% getSystemTime %></P>
</BODY>
</HTML>
10
La función page
Páginas XML y páginas Híbridas
Y el mismo código ya aplicado a una página HSP sería:
page=
<HTML>
<HEAD><TITLE>Página XML</TITLE></HEAD>
<BODY>
<H1>¡Hola mundo!</H1>
<P>Página pedida con <% getSystemTime %></P>
</BODY>
</HTML>
Aunque hay un ligero problema con estas páginas. La función getSystemTime
reside en el modulo System.Time, el cuál necesita ser importado para que la función
sea usada.
11
La función page
Páginas XML y páginas Híbridas
Con HSP no habría problemas pero con pero en páginas XML no hay ningún
lugar donde poder añadir la importación.
Para salvar este problema se introducen las páginas híbridas que contienen una
combinación de páginas XML con un nivel alto de declaraciones.
<%
import System.Time
%>
<HTML>
<HEAD><TITLE>Página XML </TITLE></HEAD>
<BODY>
<H1>¡Hola mundo!</H1>
<P>Página demandada <% getSystemTime %></P>
</BODY>
</HTML>
12
La función page
Sintaxis formal de una página
Para poder crear páginas híbridas se añade una nueva función más elaborada
de page, especificando como una página correcta en HSP, puede parecerse a:
page : : = module
| xml
| <% module %> xml
Podemos utilizar un módulo normal de HSP, un árbol completo XML, o bien
una combinación de los dos.
13
La función page
Computación embebida y mónada HSP
¿Cuál es el tipo de la función de nuestro ejemplo “hola mundo”?
Solución más simple: Dejar el tipo XML
Pero no es tan sencillo, porque permitimos cálculos impuros
cálculos con efectos laterales para ser embebidos dentro de los fragmentos
de XML.
Ejemplo de computación embebida: getSystemTime con el tipo IO Time
14
La función page
Computación embebida y mónada HSP
HSP suspende la computación embebida hasta que es evaluada explícitamente
Parece que las funciones devuelven valores XML puros, pero pueden
contener computaciones no evaluadas
No hay forma de distinguir entre valores XML puros y los que contienen
computaciones no evaluadas
15
La función page
Computación embebida y mónada HSP
Para solucionar esto se introdujo una mónada HSP
Encapsula los efectos laterales
Proporciona entorno E/S a las páginas Web
Todas las expresiones XML serán resueltas computando una mónada HSP.
Ejemplo
<p> ¡Hola mundo!</p>
Tiene tipo HSP XML a pesar de no tener efectos laterales
No es algo perfecto, pero es preferible a no tener efectos
laterales nunca
16
Sintaxis HSP
Encuentro entre XML y Haskell
HolaMundol = <p>¡Hola Mundo!</p>
Hay dos cosas interesantes que comentar
No necesitamos usar ningún mecanismo de escape para dejar el
contexto del código cuando queremos escribir el fragmente XML,
en HSP todos los fragmentos XML están garantizados para estar
siempre bien-formados.
17
Sintaxis HSP
Las expresiones malformadas darían error
helloWorld = <p>Hello World!</q>
Las etiquetas funcionan ellas solas cómo escapes
boldHelloWorld = <p><b>Hello World!</b></p>
Siempre que queramos que el contenido interno sea evaluado por una
expresión, deberemos usar caracteres de escape
hello name = <p>Hello <% name %>!</p>
18
Sintaxis HSP
Queremos también que nuestros elementos XML sean capaces de tener
atributos
RedHelloWorld :: HSP XML
redHelloWorld =
<p style="color:red">Hello World!</p>
Al igual que los hijos, los valores de atributos pueden también ser computados
a partir de expresiones embebidas
hwColor :: String -> HSP XML
hwColor c =
<p style=("color:" ++ c)>Hello World!</p>
19
Sintaxis HSP
Todas las páginas HSP deben definir y exportar una página de función
definiendo el contenido de la página.
page = <html>
<head><title>Hello World!</title></head>
<% helloBody %>
</html>
¡¡¡Ya tenemos nuestra primera página HSP!!!
20
Sintaxis HSP - Concordancia de patrones
Concordancia de Elementos
Lo primero de todo lo que podemos comparar directamente en elementos,
cómo
isImg <img/> = True
isImg _ = False
Nuestra interpretación intuitiva de lo de arriba es que implementa isImg
devolverá True si un elemento img se da, y False en otro caso
21
Sintaxis HSP - Concordancia de patrones
Concordancia de Atributos
Para concordancia de patrones en atributos, primero necesitamos
considerar cómo queremos usarlos. Lo primero de todo, en XML el orden
de atributos es irrelevante, por lo que para la instancia de dos elementos
<img src="img/myImg.jpg" alt="My image" />
y,
¡Son equivalentes!
<img alt="My image" src="img/myImg.jpg" />
22
Sintaxis HSP - Concordancia de patrones
Concordancia de Hijos
La concordancia de patrones en hijos se puede escribir cómo en este
ejemplo
getPText <p><% PCDATA t %></p> = t
Comparar un simple hijo es bastante simple, pero para ejemplos más
complicados existe un problema
“comparar un número arbitrario de elementos <p>”
o
“empezar por comparar un elemento <h1>, seguido por uno o más
ocurrencias de un elemento <h2> y un elemento <p> en la secuencia”
23
Sintaxis HSP - Concordancia de patrones
Para esto hemos desarrollado HaRP (Haskell Regular Patterns). El sistema
para patrones de expresiones regulares en Haskell
Ejemplo para obtener todo el texto de los párrafos de un documento
Denota que
getText :: XML -> [String]
debería haber
getText <body>[
0 o más p
<p><% PCDATA t %></p>*
encerrados en el
]</body> = t
elemento body
24
Sintaxis HSP – Sintaxis formal
Sintaxis formal
Extendemos la gramática Haskell con nuevas producciones de expresiones
XML, las cuales añadimos al lenguaje cómo una expresión atómica
posible
aexp ::= var
| lit
| ( exp )
...
| xml
La nueva manera de expresión, xml, puede ser también un elemento
cerrado con hijos, o una etiqueta vacía auto-contenida
xml ::= <name attrs>child...child</name>
| <name attrs/>
25
Sintaxis HSP – Sintaxis formal
Los atributos son pares nombre-valor, seguidos opcionalmente por una
expresión extra
attrs ::= attrs1 aexp
| attrs1
attrs1 ::= name = aexp ... name = aexp
Un hijo puede ser un elemento jerarquizado, PCDATA o una expresión Haskell
embebida
child ::= xml
| PCDATA
| <% exp %>
26
Sintaxis HSP – Sintaxis formal
Un nombre en XML puede ser calificado opcionalmente por un espacio de
nombres a cuyo elemento pertenece. Nuestra producción de nombre queda así
name ::= string : string
| string
donde el espacio de nombres definido anteriormente está especificado
27
Sintaxis HSP – Entorno
Las páginas HSP tienen acceso a un entorno especial que contiene
información si tenemos en cuenta el contexto en el cual son evaluadas.
Los componentes principales son:
Petición: Peticiones HTTP que iniciaron la llamada a la página
Respuesta: Respuesta HTTP que ha sido generada, la cual se enviará con
los resultados de la llamada a la página
Aplicación: Contiene datos con visibilidad de aplicación, por ejemplo
datos que persisten entre transacciones de páginas
Sesión: Contiene datos que pertenecen a un cliente específico
28
Sintaxis HSP – Entorno
Entorno de Petición
ASP
Request (“hello”)
PHP
$_REQUEST[“hello”]
HSP
getParameter “hello”
29
Sintaxis HSP – Entorno
En el entorno del programación lo más importante es consultar cadenas de
caracteres (pares nombre-valor) de la forma
param1 = valor1&…¶mn = valorn
Los parámetros en la petición pueden ser accedidos usando las funciones
getParameter :: String -> HSP (Maybe String)
readParameter :: Read a => String -> HSP (Maybe a)
30
Sintaxis HSP – Entorno
Entorno de Respuesta
Los componentes de respuesta almacenan cabeceras que serán enviadas de
vuelta al cliente receptor con los contenidos de los documentos. Estos son
conjuntos que usan funciones especializadas cómo
setNoCache :: HSP ()
En HSP ninguna salida debería ser añadida a la respuesta manualmente, todos los
contenidos deberían estar generados por la función de página, garantizando la
correcta formación del XML generado
Por ejemplo, no sería correcto
<p>Hola <% Response.write(nombre) %></p>
miMensaje :: String-> HSP XML
miMensaje nombre = <p>Hola <% nombre %></p>
31
Sintaxis HSP – Entorno
Entorno de Aplicación
El componente de Aplicación contiene datos que están compartiendo entre
todas las páginas de una aplicación, y que persiste entre peticiones simples
a páginas
El tipo de Aplicación es por si mismo abstracto, por lo que la única
manera de crear un valor del tipo que está usando la aplicación es
toApplication :: (Typeable a) => a -> Application
32
Sintaxis HSP – Entorno
El entorno de Aplicación es actualmente un tipo de envoltorio (Wrapper)
dinámico, el cual es usado para habilitar al componente de la Aplicación ser de
cualquier tipo
newtype Application =
MkApp {appContents :: Dynamic}
toApplication = MkApp . toDynamic
Para acceder a los datos de aplicación de dentro de una página, un
programador puede usar la función
getApplication :: (Typeable a) => HSP a
que devuelve un valor de su particular tipo de Aplicación
33
Sintaxis HSP – Entorno
Ejemplo (un contador)
Queremos actualizar los valores del contador necesitamos almacenarlo en
una referencia
Type MyApplication = Mvar Int
Ponemos estas declaraciones en un módulo que llamamos
MiAplicacion.hs y añadimos
toMyApplication :: MyApplication -> Application
toMyApplication = toApplication
getMyApplication :: HSP MyApplication
getMyApplication = getApplication
34
Sintaxis HSP – Entorno
Función para incrementar el contador
incrContador :: HSP ()
incrContador = do
ctr <- getMyApplication
doIO $ modifyMVar ctr (+1)
Función para leer el valor actual del contador
leerContador :: HSP Int
leerContador = do
ctr <- getMyApplication
doIO $ readMVar ctr
35
Sintaxis HSP – Entorno
Ya sólo queda darle un valor inicial al contador
En el modulo Aplicación.hsp primeramente hemos de importar
MiAplicacion.hs, y la definición
initApplication = do
ctr <- newMVar 0
return $ toMyApplication ctr
36
Sintaxis HSP – Entorno
La página
import MiAplicacion
page = do
incrementarContador
<html>
<head>
<title>Hola visitante nr <%
leerContador %>
</title>
</head>
<body>
<h1>¡Hola!</h1>
<p>Eres el visitante nr <%
leerContador %> de esta página.
</p>
</body>
</html>
37
Sintaxis HSP – Entorno
Entorno de Sesión
Los componentes de Sesión son un repositorio de datos que deja a las
páginas mantener un estado entre transacciones
Acceso al repositorio
getSessionVar :: String -> HSP (Maybe String)
setSessionVar :: String -> String -> HSP ()
Configurar tiempo de vida
setSessionExpires :: ClockTime -> HSP ()
Forzando su terminación
almacenados en el lado del
abandon :: HSP ()
cliente usando cookies
38
HJavaScript
Surgen la necesidad de un lenguaje script que pueda dar funcionalidad a
nuestras páginas del lado del cliente
HJScript se ha desarrollado con dos metas:
Proveer al programador una sintaxis lo más abstracta posible
Proveer una sintaxis cómo la original (JavaScript)
Obviamente esto no es posible
39
HJavaScript
Para modelar un lenguaje imperativo vamos a trabajar con una mónada
La mónada será escritora-estado
Parte escritora: Usada para el código JavaScript a la salida
Parte estado: Usada para la gestión del gensym
40
HJavaScript
Las 2 funciones básicas en la mónada, aparte de devolver y registrar son
newVarName :: HJScript String
newVarName = do s <- get
put $ s+1
return $ “var” ++ show s
outputCode :: JsStmt () -> HJScript ()
outputCode = tell
41
HJavaScript
También necesitamos una función evaluadora que genere el código de salida
hjscript :: HJScript t -> HJState -> (t, JSBlock ())
hjscript script s = runWriter $ runStateT script s
y una función que nos deja evaluar una computación dentro de otra:
hjsInside :: HJScript t -> HJScript (t, JSBlock ())
hjsInside script = censor (const EmptyBlock) $ listen script
42
HJavaScript
Sintaxis
Para declarar una variable
nombreVar <- var
nombreVar <- varWith valorInicial
Para declarar una función
function (a,b) {
return a+b
}
En JavaScript
function \(a,b) ->
return (a+:b)
En HJavaScript
43
HJavaScript
Elección de un símbolo operador $$
Así para invocar funciones en HJavaScript podremos hacerlo así
call myFunction (a,b)
O bien así
myFunction$$(a,b)
44
HJavaScript
Usar métodos de objetos en JavaScript
Math.abs(n)
d.getYear()
En HJavaScript sería
Math#abs$$(n)
d#getYear()
45
HJavaScript
Para integrar HJavaScript con el resto de HSP necesitamos escribir instancias
para IsXML y IsAttrValue
IsXML es necesario para
Ejecutar un script cuando la página se carga
Definir funciones en la sección de cabecera
IsAttrValue es necesario para
Atributos de eventos: onClick, onEvent, …
46
HJavaScript
Instancia isXML
instance IsXML (JsBlock ()) where
toXML b =
<script language=”JavaScript”>
<% pprBlock b %>
</script>
Instancia isAttrValue
instance IsAttrValue (JsBlock ()) where
toAttrValue b = toAttrValue $ pprBlock b
47
Foro en HSP
Diseño del foro:
Foro organizado en hilos
Cada hilo consta de uno o más mensajes
Cada mensaje consta de:
Texto
Quién lo escribió
Cuándo lo escribió
48
Foro en HSP
Configuraremos una base de datos
Inicialmente suponemos que podemos acceder a la base de datos
Empezaremos desarrollando un foro muy simple en el que sólo se muestre un
mensaje, y lo iremos ampliando gradualmente
49
Foro en HSP
Definición de registros
data Hilo = Hilo {
tema :: String,
mensajes :: [Mensaje]
}
data Mensaje = Mensaje {
autor, contenido :: String,
fecha :: CalenderTime
}
50
Foro en HSP
Para mostrar un mensaje:
mostrarMensaje :: Mensaje -> XML
Información del mensaje grabado en si mismo
o bien
mostrarMensaje :: Mensaje -> HSP XML
Información extra de otras fuentes
51
Foro en HSP
Nos quedamos con la segunda opción
mostrarMensaje :: Mensaje-> HSP XML
mostrarMensaje mensaje =
<fieldset>
<legend>
<b><% mensaje#autor %></b>
<i><% mensaje#fecha %></i>
</legend>
<% nl2br $ mensaje#contenido %>
</fieldset>
52
Foro en HSP
Se mostraría algo así
53
Foro en HSP
Para simplificar el foro, esta será la manera por defecto de mostrar un mensaje
instance IsXML Mensaje where
toXML = mostrarMensaje
Ahora vamos a definir una función para mostrar un hilo entero
Asumimos que todos los hilos contienen al menos un mensaje
Colocamos cada mensaje debajo del siguiente
54
Foro en HSP
Función que muestra un hilo
mostrarHilo :: Hilo -> HSP XML
mostrarHilo hilo = do
let disposicionMensajes = foldl1 (^^) $ map block $ hilo#mensajes
enlacePrincipal = aLink “indice.hsp” “Volver al índice”
toXML $ h1 (hilo#tema) ^^ enlacePrincipal ^^ disposicionMensajes
^^ enlacePrincipal
^^ Es un combinador que coloca
cualquier objeto en disposición
vertical.
55
Foro en HSP
Código de: mostrarHilo.hsp
import HSP Forum.Databases (getThread)
import HSP.Layout
pagina = do mthid <- getParameter “threaded”
case mthid of
Nothing -> redirect “indice.hsp”
Just thId -> do
mthread <- darHilo thId
case mthread of
Nothing -> redirect “indice.hsp”
Just hilo -> paginaHilo hilo
paginaHilo hilo =
<html>
<head><title><% hilo#tema %></title>
<body><% mostrarHilo hilo %></body>
</html>
mostrarHilo hilo = ...
mostrarMensaje mensaje = ...
56
Foro en HSP
Quedaría algo así
57
Foro en HSP
Ahora vamos a definir la página índice de los hilos
Necesitamos recuperar la id de los hilos y la línea del tema para todos los
mensajes
Dar formato a los pares <id,tema> en un enlace que nos llevará al hilo.
Listar todos los enlaces
58
Foro en HSP
Función para crear un enlace a un tema
enlaceHilo :: Int -> String -> HSP XML
enlaceHilo threaded =
aLink (“mostrarHilo.hsp?idHilo=” ++ show threaded)
Función para listar los hilos
listaHilos :: [(Int, String)] -> HSP XML
listaHilos hilos = ul $ map (uncurry enlaceHilo) hilos
59
Foro en HSP
La página dinámica resultante
page = do mthinfo <- darInformacionHilo
let thinfo = maybe [] id mthinfo
<html>
<head><title><% nombreForo %></title></head>
<body>
<% h1 nombreForo %>
<% listaHilos thinfo %>
</body>
</html>
60
Foro en HSP
Conexiones a la base de datos
HaskellDB
Hay problemas con accesos concurrentes
Asegurar que sólo hay un recurso de conexión
Implementar un mecanismo para controlar quién y cuándo lo usa
61
Foro en HSP
Creamos un módulo llamado MiAplicacion.hs
donde definimos
type ConexionBD = (Database -> IO a) -> IO a
type MiAplicacion = (Mvar (),ConexionBD)
myToApplication :: MyApplication -> Application
myToApplication = toApplication
myGetApplication :: HSP MyApplication
myGetApplication = toApplication
62
Foro en HSP
Definimos dos funciones para trabajar sobre las conexiones
conexionBD :: (Database -> IO a) -> HSP a
conexionBD q = do (_, conn) <- myGetApplication
doIO $ conn q
conexionBDsegura :: (Database -> IO a) -> HSP a
conexionBDsegura q = do (lock, conn) <- myGetApplication
doIO $ bracket_
Asegura que el
(takeMVar lock)
programa no se
(putMVar lock ())
pare si se produce
(conn q)
una excepción
63
Foro en HSP
Nos queda instalar el fichero Aplicacion.hs
initApplication = do lock <- newMVar ()
return $ myToApplication (lock, conn)
Asumimos que conn está definido en otra parte, no lo veremos en el futuro
dado que HaskellDB es muy dependiente del sistema de bases de datos usado.
64
Foro en HSP
Para obtener todos los mensajes de un hilo particular
darHilo :: Int -> HSP (Maybe Hilo)
darHilo idHilo = do
r1 <- conexionBD $ \db -> query db consultaHilos
case r1 of
[] -> return Nothing -- No existe el hilo
[rec] -> do
r2 <- conexionBD $ \db -> query db consultaMensajes
return $ Hilo { tema = rec!Th.tema,
mensajes = map hacerMensaje r2 }
where consultaHilos = do
t <- table Th.hilos
restrict (t!Th. idHilo.==. constant idHilo)
return t
consultaMensajes = do
t <- table Th.mensajes
restrict (t!Th. idHilo.==. constant idHilo)
order [asc t Th.mensajeNr]
return t
hacerMensaje rec = Mensaje {
autor = rec!Th.autor,
time = rec!Th.fecha,
contenidos = rec!Th.contenido }
65
Foro en HSP
Función para almacenar hilos en su tabla correspondiente
darInformacionHilo :: HSP [(Int, String)]
darInformacionHilo = do
r1 <- conexionBD $ \db -> query db (table Th.hilo)
return $ map (\rec -> (rec!Th.idHilo, rec!Th.tema)) r1
Creando/Enviando nuevos mensajes
Comenzar un nuevo hilo o responder a un hilo existente
Responder a un hilo se hará en una página aparte
Visualizar mensajes tras enviarlos
Introducimos una página intermedia entre la página de envío y la página
que muestra los datos
66
Foro en HSP
Página intermedia
page = do
[thId, autor, contenidos, tema] <mapM getParameter [“idHilo”, “autor”,“contenidos”, “tema”]
ti <- case thId of
Just thId -> do
conexionBDsegura $ insertPost autor contenidos
thId
return thId
Nothing -> do
conexionBDsegura $
insertarHiloDeMensajes tema autor mensaje
redirect $ “mostrarHilo.hsp?idHilo=” ++ show ti
where insertarMensaje autor conts thid = \db -> do
let (Just aut, Just txt) = (autor, conts)
time <- getCurrentTime
67
Foro en HSP
insert db Th.posts (Th.idHilo << thId #
Th.autor << autor #
Th.fecha << time #
Th.contenido << txt )
insertarHiloDeMensajes tema autor conts = \db -> do
let (Just aut, Just txt) = (autor, conts)
time <- getCurrentTime
insert db Th.hilos (Th.tema << tema)
[rThId] <- query db maxThidConsulta
let thId = rThId!Th.idHilo
insert db Th.mensajes (Th.idHilo << thId #
Th.autor << autor #
Th.fecha << fecha #
Th.contenido << txt )
maxThidConsulta = do
t <- table Th.hilos
preoject (Th.idHilo << max t!Th.idHilo)
68
Foro en HSP
Formulario para enviar Mensaje
formularioMensaje :: (Maybe Int) -> HSP XML
formularioMensaje mthreadId =
<form method=Post action=“handledata.hsp”>
<% borderTable 0 $
filaDelTema ++
[filaAutor,
filaContenido,
[idHiloOculto, botonEnvio]
]
%>
</form>
69
Foro en HSP
where filaDelTema =
case mthreadId of
Just _ -> []
Nothing -> [withLabel textField “tema”]
filaAutor = withLabel textField “autor”
filaContenido = withLabel textArea “contenido”
idHiloOculto = fmap (hidden “idHilo”) mthreadId
botonEnvio = submit “Enviar” `set`
[“value” := “Submit post”]
Definimos la función withLabel
withLabel :: (String -> HSP XML) -> String -> [HSP XML]
withLabel f n@(c:cs) =
[label n (toUpper c : cs ++ “:”) , f n]
70
Foro en HSP
Para incluir el formulario con hilos, necesitamos retocar ligeramente el
código para asegurar que tenemos acceso al id del hilo
paginaHilo hilo idHilo =
<html>
<head><title><% hilo#tema %></title></head>
<body>
<% mostrarHilo hilo
^^ formularioMensaje (Just idHilo) %>
</body>
</html>
71
Foro en HSP
La página dedicada a comenzar los hilos, comenzarHilo.hsp, será
import formularioMensaje
page = <html>
<head><title>Nuevo Hilo</title></head>
<body><% formularioMensaje Nothing %></body>
</html>
72
Conclusiones
La utilización de la potencia de un lenguaje funcional como es Haskell junto
con la simplicidad de la utilización de un lenguaje script han hecho de HSP un
lenguaje tan bueno como sus iguales.
El área donde debemos realizar mayores esfuerzos para mejorar el lenguaje es
en la construcción de librerías, donde los otros lenguajes tienen mayor ventaja.
La meta inicial en la construcción del diseño del lenguaje HSP era que tuviera
el mismo poder expresivo que Haskell para atraer al programador funcional
experto, y además fuera muy intuitivo para el programador Web novato.
El problema de que no esté muy extendido es que necesita de una comunidad
activa que ayude con extensiones y mejoras, como librerías, manuales y
programas de ejemplos.
73
Futuros trabajos
El modelo de programación presentado define la sintaxis y la semántica de la
extensión XML a Haskell. Pero hay algunas extensiones que podrían
introducirse para simplificar la forma de expresar con certeza algunos
modismos.
Una extensión que vendría conveniente cuando los patrones enlacen
elementos es permitir resumir el nombre del elemento en la sintaxis XML
concreta.
Otra posible extensión es permitir una forma de búsqueda de atributo que
tendrá éxito independientemente de la existencia del atributo o no.
74
Futuros trabajos
Otra cosa a tener en cuenta, es la implementación, ya que ésta proporciona una
completa funcionalidad al sistema HSP.
Una solución al horrible mensaje de error que aparece en el pre-procesador
sintáctico puro, antes de comprobar los tipos es extender el pre-proceso con un
analizador de tipos que pueda manejar nuestra sintaxis XML tan bien como el
código Haskell incluido en todas las extensiones que HSP usa.
Crear numerosos documentos de ayuda en pdf, y conseguir desarrollar un gran
número de librerías para conexiones a bases de datos.
75
Bibliografía
Documentos y libros
Erik Meijer. Server-side Web Scripting in Haskell. Journal of Functional
Programming, 1(1), 1998.
Erik Meijer and Mark Shields. XMλ: A Functional Language for Constructing
and Manipulating XML Documents. (Draft), 1999.
Paul Graunke, Shriram Krishnamurthi, Steve Van der Hoeven and Matthias
Felleisen. Programming the Web with High-level Programming Languages. In
Proceedings of the European Symposium On Programming, 2001.
Erik Meijer and Danny van Velzen. Haskell Server Pages: Functional
Programming and the Battle for the Middle Tier. In Proceedings of the Haskell
Workshop, 2000.
Ruiz, B.C., Gutierrez, F., Guerrero, P., Gallardo, J.E. Razonando con Haskell.
Una introducción a la Programación Funcional. Los autores. 2000
Broberg, Niklas. Thesis for the Degree of Master of Science.Haskell Server
Pages (DRAFT) Chalmers University of Technology 2005
76
Bibliografía
ASP.NET home. http://msdn.microsoft.com/asp.net/.
PHP: Hypertext Processor home. http://www.php.net/.
WASH home.http://www.informatik.uni-freiburg.de/~thiemann/haskell/WASH/.
Extensible Markup Language. http://www.w3c.org/XML.
Buscadores científicos
GOOGLE Scholar. http://scholar.google.com/
SCIRUS. Buscador de ciencia. http://www.scirus.com/srsapp/
Buscador de publicaciones científicas y de páginas Web de contenido científico.
77