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&…&paramn = 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