<?xml version="1.0" encoding="ISO-8859-1"?><article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<front>
<journal-meta>
<journal-id>1683-0789</journal-id>
<journal-title><![CDATA[Acta Nova]]></journal-title>
<abbrev-journal-title><![CDATA[RevActaNova.]]></abbrev-journal-title>
<issn>1683-0789</issn>
<publisher>
<publisher-name><![CDATA[Universidad Católica Boliviana]]></publisher-name>
</publisher>
</journal-meta>
<article-meta>
<article-id>S1683-07892012000100003</article-id>
<title-group>
<article-title xml:lang="es"><![CDATA[Interoperabilidad de Haskell con otros lenguajes de programación mediante XML]]></article-title>
<article-title xml:lang="en"><![CDATA[Haskell interoperability with other programming languages using XML]]></article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname><![CDATA[Sejas]]></surname>
<given-names><![CDATA[Alvaro Israel]]></given-names>
</name>
<xref ref-type="aff" rid="A01"/>
</contrib>
</contrib-group>
<aff id="A01">
<institution><![CDATA[,Universidad Mayor de San Simón  ]]></institution>
<addr-line><![CDATA[ Cochabamba]]></addr-line>
<country>Bolivia</country>
</aff>
<pub-date pub-type="pub">
<day>00</day>
<month>03</month>
<year>2012</year>
</pub-date>
<pub-date pub-type="epub">
<day>00</day>
<month>03</month>
<year>2012</year>
</pub-date>
<volume>5</volume>
<numero>3</numero>
<fpage>374</fpage>
<lpage>389</lpage>
<copyright-statement/>
<copyright-year/>
<self-uri xlink:href="http://www.scielo.org.bo/scielo.php?script=sci_arttext&amp;pid=S1683-07892012000100003&amp;lng=en&amp;nrm=iso"></self-uri><self-uri xlink:href="http://www.scielo.org.bo/scielo.php?script=sci_abstract&amp;pid=S1683-07892012000100003&amp;lng=en&amp;nrm=iso"></self-uri><self-uri xlink:href="http://www.scielo.org.bo/scielo.php?script=sci_pdf&amp;pid=S1683-07892012000100003&amp;lng=en&amp;nrm=iso"></self-uri><abstract abstract-type="short" xml:lang="es"><p><![CDATA[En este artículo se propone un enfoque para la integración de Haskell con lenguajes foráneos, usando XML como mecanismo para expresar llamadas remotas a servicios implementados en Haskell. HermesPC es la solución planteada (e implementada) que consiste de un protocolo y un servidor que permite el acceso remoto a las funciones Haskell. Además se presenta un ejemplo del mundo real (HermesRss) en el que se utiliza la solución implementada.]]></p></abstract>
<abstract abstract-type="short" xml:lang="en"><p><![CDATA[This paper proposes an approach for the integration of Haskell with foreign programming languages, using XML as a mechanism to compose remote calls to services implemented in Haskell. HermesPC is the proposed (and implemented) solution, it is composed of a protocol and a server which allows remote access to Haskell functions. Moreover, a real world example (HermesRss) that uses the solution is presented.]]></p></abstract>
<kwd-group>
<kwd lng="es"><![CDATA[Programación funcional]]></kwd>
<kwd lng="es"><![CDATA[Haskell]]></kwd>
<kwd lng="es"><![CDATA[.Net]]></kwd>
<kwd lng="es"><![CDATA[XML]]></kwd>
<kwd lng="es"><![CDATA[servicio remoto]]></kwd>
<kwd lng="en"><![CDATA[Functional programming]]></kwd>
<kwd lng="en"><![CDATA[Haskell]]></kwd>
<kwd lng="en"><![CDATA[.Net]]></kwd>
<kwd lng="en"><![CDATA[XML]]></kwd>
<kwd lng="en"><![CDATA[remote service]]></kwd>
</kwd-group>
</article-meta>
</front><body><![CDATA[ <p align="center"><font size="4" face="Verdana"><b>Interoperabilidad de Haskell    con otros lenguajes de programación mediante XML</b></font></p>     <p align="center">&nbsp;</p>     <p align="center"><font size="3" face="Verdana"><b>Haskell interoperability with    other programming languages using XML</b></font></p>     <p align="center">&nbsp;</p>     <p align="center">&nbsp;</p>     <p align="center"><font size="2" face="Verdana"><b>Alvaro Israel Sejas</b></font></p>     <p align="center"><font size="2" face="Verdana">Universidad Mayor de San Simón,    Cochabamba - Bolivia</font></p>     <p align="center"><font size="2" face="Verdana"><a href="mailto:isoujiro@gmail.com">isoujiro@gmail.com</a></font></p>     <p align="center">&nbsp;</p>     <p align="center">&nbsp;</p> <hr align="center" noshade>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana"><b>Resumen</b>: </font></p>     <p align="justify"><font size="2" face="Verdana">En este artículo se propone un    enfoque para la integración de Haskell con lenguajes foráneos, usando XML como    mecanismo para expresar llamadas remotas a servicios implementados en Haskell.    HermesPC es la solución planteada (e implementada) que consiste de un protocolo    y un servidor que permite el acceso remoto a las funciones Haskell. Además se    presenta un ejemplo del mundo real (HermesRss) en el que se utiliza la solución    implementada.</font></p>     <p align="justify"><font size="2" face="Verdana"><b>Palabras clave</b>: Programación    funcional, Haskell, .Net, XML, servicio remoto.</font></p> <hr align="center" noshade>     <p align="justify"><font size="2" face="Verdana"><b>Abstract</b>: </font></p>     <p align="justify"><font size="2" face="Verdana">This paper proposes an approach    for the integration of Haskell with foreign programming languages, using XML    as a mechanism to compose remote calls to services implemented in Haskell. HermesPC    is the proposed (and implemented) solution, it is composed of a protocol and    a server which allows remote access to Haskell functions. Moreover, a real world    example (HermesRss) that uses the solution is presented.</font></p>     <p align="justify"><font size="2" face="Verdana"><b>Keywords</b>: Functional programming,    Haskell, .Net, XML, remote service.</font></p> <hr align="JUSTIFY" noshade>     <p align="justify">&nbsp;</p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>1.  Introducción</b></font></p>     <p align="justify"><font size="2" face="Verdana">La integración de Haskell con    otros lenguajes de programación es un tema que ha sido abordado por varias iniciativas    desde diferentes enfoques, cada uno con sus ventajas e inconvenientes.</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">Varias de las tecnologías Haskell    implementadas actualmente tienen su propio enfoque para tratar con el problema    de interoperabilidad, pero como se verá más adelante éstas presentan ciertas    desventajas, lo cual nos motiva a proponer una solución desde otro punto de    vista.</font></p>     <p align="justify"><font size="2" face="Verdana">En este artículo se pretende    mostrar una propuesta de solución que se apoya en el uso de XML, algo similar    a los Servicios Web pero por ahora más simple. XML es la tecnología que se utiliza     para el intercambio de información estructurada porque permite lograr independencia    de la plataforma con la que se quiere la interoperabilidad.</font></p>     <p align="justify"><font size="2" face="Verdana">La idea es trabajar en busca    de un protocolo que permita hacer invocaciones remotas a funciones de Haskell    y un servidor que provea éstas funciones, lo cual es natural implementar usando    las tecnologías de red que provee Haskell en su intérprete Ghc.</font></p>     <p align="justify"><font size="2" face="Verdana">El artículo se ha organizado    de la siguiente forma: en la sección dos se presenta un resumen de algunas tecnologías    que abordan el dominio del problema y presentan diferentes enfoques de solución;    en el apartado tres se hace una introducción a HaXml que es una librería para    procesamiento de XML cuya funcionalidad es indispensable en este caso; en la    sección 4 se presenta una explicación de la solución planteada; y finalmente    en la parte 5 se muestra un ejemplo de uso de la solución propuesta en una aplicación    de la vida real.</font></p>     <p align="justify">&nbsp;</p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>2.  Tecnologías Haskell para    interoperabilidad con lenguajes foráneos</b></font></p>     <p align="justify"><font size="2" face="Verdana">Debido a la naturaleza actual    de algunas aplicaciones, un lenguaje de programación debe poseer algunos mecanismos    que le permitan interactuar con otros lenguajes, para así ampliar sus posibles    aplicaciones. Haskell posee varias tecnologías que le permiten interactuar con    lenguajes foráneos, a continuación se presentan algunas de ellas.</font></p> <h3 align="justify">&nbsp;</h3> <h3 align="justify"><font size="2" face="Verdana">2.1. FFI</font></h3>     <p align="justify"><font size="2" face="Verdana">La Interfaz de Lenguajes Foráneos    de Haskell (FFI o Foreign Function Interface [1]) es una especificación que    añade a Haskell la funcionalidad de interactuar con otros lenguajes de programación,     es decir que permite llamar desde Haskell a código implementado en un lenguaje    diferente y viceversa. </font></p>     <p align="justify"><font size="2" face="Verdana">Antes de presentar el objetivo    principal de FFI se debe definir dos conceptos: el contexto Haskell es el contexto    de ejecución de la máquina abstracta en la cual Haskell está basado; mientras    que un contexto externo es otro contexto diferente a este último.</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">El objetivo principal de FFI    es permitir el acceso desde un contexto Haskell a un contexto externo mediante    una interfaz programable, es decir el poder acceder a datos y funciones de un    contexto externo desde Haskell y lo inverso.</font></p>     <p align="justify"><font size="2" face="Verdana">La extensión a la especificación    de Haskell para soportar FFI solo agrega las siguientes producciones:</font></p>     <p align="justify"><font size="2" face="Verdana"> <b>reservedid -&gt; foreign    specialid -&gt; export | safe | unsafe | ccall| cplusplus | dotnet | jvm | stdcall|    system-specific calling conventions</b></font></p>     <p align="justify"><font size="2" face="Verdana">Mediante estas producciones se    puede declarar funciones que permiten invocar entidades del contexto externo    así como también declarar funciones del contexto Haskell para ser invocadas    por el contexto externo.</font></p>     <p align="justify"><font size="2" face="Verdana">Por ejemplo, para llamar a la    función seno de la librería math.h de C, se debe hacer una declaración import,    de la siguiente forma:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>foreign import ccall &quot;math.h    sin&quot; seno::CDouble -&gt; CDouble</b></font></p>     <p align="justify"><font size="2" face="Verdana">En la declaración: &#8217;ccall&#8217;    es la convención de llamada, &#8217;math.h sin&#8217; es el identificador de    la entidad externa, &#8217;seno&#8217; es el identificador de la función y &#8217;CDouble&#8217;    el tipo utilizado en la función.</font></p>     <p align="justify"><font size="2" face="Verdana">En el caso opuesto, para poder    hacer que una función implementada en Haskell esté disponible para ser llamada    desde otro lenguaje, se debe hacer una declaración export, de la siguiente forma:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>foreign export ccall &quot;restarInt&quot;    (-):: Int -&gt; Int -&gt; Int</b></font></p>     <p align="justify"><font size="2" face="Verdana">En la declaración, &#8217;ccall&#8217;    es la convención de llamada, &#8217;restarInt&#8217; es el identificador de    la función, &#8217;(-)&#8217; es lo que será evaluado e &#8217;Int -&gt; Int    -&gt; Int&#8217; es la instancia del tipo de la función exportada.</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">Esto es básicamente lo que provee    FFI para que Haskell pueda interactuar con otros lenguajes de programación,    el intercambio de información se puede hacer mediante los tipos de datos básicos    soportados por FFI.</font></p> <h3 align="justify">&nbsp;</h3> <h3 align="justify"><font size="2" face="Verdana">2.2. Hugs98 para .Net</font></h3>     <p align="justify"><font size="2" face="Verdana">Hugs98 para .Net [2] es una extensión    de Hugs98 que permite la interoperabilidad entre la plataforma .Net y Haskell.</font></p>     <p align="justify"><font size="2" face="Verdana">Esta extensión es provista como    una implementación del intérprete Hugs98 que agrega algunas producciones al    lenguaje, mediante las cuales se puede instanciar y usar objetos .Net desde    Haskell y también permite llamar a funciones Haskell desde cualquier lenguaje    de la plataforma .Net.</font></p>     <p align="justify"><font size="2" face="Verdana">La motivación de esta implementación    es completamente pragmática, el intérprete Hugs98 opera lado a lado con el .Net    runtime, lo que permite que segmentos de código de un lenguaje hagan invocaciones    a segmentos de código del otro lenguaje, es decir que no es un compilador que    transforma de código Haskell a código intermedio de .Net (MSIL<sup><a href="#ref1">1</a></sup>)</font></p>     <p align="justify"><font size="2" face="Verdana">De manera similar a FFI, Hugs98    para .Net accede a un contexto externo mediante producciones que agrega a la    especificación de Haskell, las cuales son:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>ffidecl : ...    <br>   | &#8217;foreign&#8217; &#8217;import&#8217; &#8217;dotnet&#8217;     <br>   &quot;spec-string&quot; varName &#8217;::&#8217; ffiType</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">spec-string : (&#8217;static&#8217;)?        <br>   (&#8217;field&#8217;|&#8217;ctor&#8217;|&#8217;method&#8217;)? (&#8217;[&#8217;    assemblyName &#8217;]&#8217;)?    ]]></body>
<body><![CDATA[<br>   .NETName</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">ffiType : PrimType -&gt;    ffiType     <br>   | IO PrimType    <br>   | PrimType</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">PrimType = standard    FFI types + Object a + String</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Las producciones &#8217;foreign&#8217;    e &#8217;import&#8217; tienen el mismo objetivo que en la especificación FFI,    &#8217;export&#8217; no está implementada en Hugs98.Net, y &#8217;dotnet&#8217;    es el identificador de la convención de llamada.</font></p>     <p align="justify"><font size="2" face="Verdana">Las palabras reservadas listadas    en &#8217;spec-string&#8217; hacen referencia a la entidad que se quiere llamar,    es decir: &#8217;static&#8217; para una entidad estática, &#8217;field&#8217;    para un atributo de un objeto, &#8217;ctor&#8217; es el constructor de objetos,    &#8217;method&#8217; para un método; &#8217;assemblyName&#8217; y &#8217;.NETName&#8217;    para hacer referencia a una clase de .Net.</font></p>     <p align="justify"><font size="2" face="Verdana">Por ejemplo una llamada a un    método estático tendría la siguiente forma:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>foreign import dotnet &quot;static    System.Console.Write&quot; </b></font></p>     <p align="justify"><font size="2" face="Verdana"><b>saludar :: String -&gt; IO    String</b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">El tipo de la función que se    quiere importar tiene que ser compatible con el tipo de .Net correspondiente,    de lo contrario ocurre una excepción IO.</font></p>     <p align="justify"><font size="2" face="Verdana">Las llamadas a funciones Haskell    se realizan mediante una librería (Hugs Server API) que ofrece un API para acceder    a algunas funcionalidades del intérprete Hugs98 para .Net, pero esto es sólo    posible partiendo desde el lado Haskell (enviando un referencia de una instancia    del intérprete al programa .Net) lo cual es un serio inconveniente.</font></p>     <p align="justify"><font size="2" face="Verdana">Finalmente podemos mencionar    que se puede también emular herencia y hacer llamadas con estilo orientado a    objetos; además que Hugs98.Net contiene una herramienta que permite la generación    automática de declaraciones FFI y tipos de objetos para clases .Net llamada    hswrapgen.</font></p>     <p align="justify">&nbsp;</p> <h3 align="justify"><font size="2" face="Verdana">2.3. H/Direct</font></h3>     <p align="justify"><font size="2" face="Verdana">H/Direct[3] es una interfaz de    lenguaje foráneo para Haskell, que en lugar de confiar en tipos específicos    a lenguajes de programación, compila IDL (Interface Definition Language) a código    que transforma los datos a través de la interfaz. Permite así a Haskell llamar    a código implementado en C o empaquetado como COM (Component Object Model);    y también a los componentes Haskell ser envueltos en C o COM para ser llamados    desde otros lenguajes.</font></p>     <p align="justify"><font size="2" face="Verdana">Para el caso de interoperabilidad    entre dos lenguajes, definir el tipo de un procedimiento en una notación formal    es lo más apropiado. Basándose en esa notación H/Direct genera código de tubería    que convierte los parámetros para que puedan ser comprendidos por el otro lenguaje,    entonces llama al procedimiento extranjero usando la convención de llamada del    mencionado lenguaje y después vuelve a convertir los resultados para que puedan    ser entendidos nuevamente.</font></p>     <p align="justify"><font size="2" face="Verdana">Para resolver el problema de    la conversión de tipos, H/Direct usa IDL, porque no es un lenguaje de programación    sino un lenguaje de especificación, este le permite definir tanto los tipos    de las funciones como también los datos que toma como argumentos, todo de una    manera independiente de la arquitectura y del lenguaje.</font></p>     <p align="justify"><font size="2" face="Verdana">H/Direct permite las siguientes    operaciones:</font></p>     <p align="justify"><font size="2" face="Verdana">· Acceder a librerías externas</font></p>     <p align="justify"><font size="2" face="Verdana">· Exportar funciones Haskell    al mundo exterior</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">· Usar objetos COM desde Haskell</font></p>     <p align="justify"><font size="2" face="Verdana">· Implementar componentes COM    con Haskell</font></p>     <p align="justify"><font size="2" face="Verdana">Para implementar un componente    COM con Haskell y H/Direct se requiere lo siguiente:</font></p>     <p align="justify"><font size="2" face="Verdana">· La aplicación implementada    en Haskell</font></p>     <p align="justify"><font size="2" face="Verdana">· La especificación IDL para    las funciones que se quiere acceder desde el exterior</font></p>     <p align="justify"><font size="2" face="Verdana">· El código de tubería que H/Direct    genera automáticamente</font></p>     <p align="justify"><font size="2" face="Verdana">· La librería COM que exporta    las funciones de Haskell, y una librería en C que provee algún código de soporte    de tiempo de corrida</font></p>     <p align="justify"><font size="2" face="Verdana">Para comprender mejor lo que    es H/Direct se presenta un ejemplo [4][5]. En el que se empaqueta una función    de Haskell como un componente COM, en la forma de una librería DLL, para luego    poder ser usada desde otros programas.</font></p>     <p align="justify"><font size="2" face="Verdana">Se parte definiendo la estructura    de la función en IDL (archivo Hola.idl) e implementando algunas otras definiciones    requeridas:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>...</b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">[ object, uuid(2cf00d46-4f67-11dc-8314-0800200c9a66)]    </font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">interface Ihola : IUnknown    {HRESULT saludar([out,retval] BSTR *out); };</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">[ object, uuid(4df11530-4f67-11dc-8314-0800200c9a66)]</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">coclass Hola { [default]interface    Ihola; };</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">El anterior listado constituye    la definición de la función &#8216;saludar&#8217;, que lo único que hace es    retornar una cadena.</font></p>     <p align="justify"><font size="2" face="Verdana">A continuación, usando una de    las herramientas de H/Direct se generan dos archivos, el proxy que implementará    una interfaz COM mediante la cual se podrá acceder al componente y también se    genera el esqueleto de la función:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>$ ihc -fcom Hola.idl -s --skeleton</b></font></p>     <p align="justify"><font size="2" face="Verdana">Se debe completar código en el    archivo con el esqueleto de la función y después compilar los dos archivos generados:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>$ ghc -c -ffi -package com    Hola.hs HolaProxy.hs</b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">Para generar una librería DLL    se debe crear un módulo Main, copiar los archivos ComDllMain.lhs y dllStub.c    al directorio del ejemplo y compilarlos junto con el módulo Main:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>$ ghc -c -ffi -package com    Main.hs ComDllMain.lhs dllStub.c</b></font></p>     <p align="justify"><font size="2" face="Verdana">Finalmente se copia el archivo    ComServer.def y se procede a generar la librería DLL:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>$ ghc --mk-dll -o comdll.dll    -optdll-def -optdllComServer.def Hola.o HolaProxy. o Main.o ComDllMain.o dllStub.o    -fglasgow-exts -syslib com</b></font></p>     <p align="justify"><font size="2" face="Verdana">La librería DLL generada puede    ser usada desde cualquier lenguaje que soporte esta tecnología.</font></p> <h3 align="justify">&nbsp;</h3> <h3 align="justify"><font size="2" face="Verdana">2.4  Comparativa</font></h3>     <p align="justify"><font size="2" face="Verdana">Cada una de las soluciones expuestas    presenta ventajas y desventajas en cuanto a su forma de tratar con el problema    de interacción de Haskell con lenguajes foráneos. </font></p>     <p align="justify"><font size="2" face="Verdana">FFI está implementada tanto por    Ghc como por Hugs, lo cual la hace bastante accesible, pero la implementación    actual en Ghc solo soporta llamadas foráneas a lenguajes con la convención de    llamada de C. La implementación de FFI (en Ghc) requiere que además se deba    implementar la convención de llamada del lenguaje con el que se quiere usar    (cuando este es diferente de C), lo cual hace de esta interfaz muy dependiente    de la plataforma, esto es una debilidad para el desarrollo con esta tecnología.</font></p>     <p align="justify"><font size="2" face="Verdana">Hug98 para .Net implementa la    mitad de la funcionalidad de FFI, y si bien posee de un mecanismo para llamar    a funciones Haskell desde .Net, todo este mecanismo fue implementado solo para    probar conceptos, no está orientado a ser un producto que pueda usarse en producción,    no se cuenta con soporte en caso de encontrar algún problema, lo cual es un    gran inconveniente al momento de implementar aplicaciones del mundo real y querer    usarlo.</font></p>     <p align="justify"><font size="2" face="Verdana">H/Direct tiene uno de los mejores    enfoques, el uso de IDL lo hace una solución bastante completa, pero una de    sus debilidades es el alto grado de conocimiento de la tecnología COM y lenguaje    C que se necesita para poder utilizarlo, además de su escasa documentación y    soporte. Por otro lado, al encapsular un programa de Haskell en una librería    DLL se le quita cierto grado de independencia al resultado de H/Direct, puesto    que no todas las implementaciones de los lenguajes de programación soportan    el uso de librerías DLL.</font></p>     <p align="justify"><font size="2" face="Verdana">Para tener una visión más clara    al respecto, se presenta la siguiente tabla comparativa:</font></p>     ]]></body>
<body><![CDATA[<p align=center><font size="2" face="Verdana"><img width=579 height=178 src="/img/revistas/ran/v5n3/v5n3a03-t01.jpg"></font></p>     <p align="center"><font size="2" face="Verdana"><b>Tabla 1:&nbsp;&nbsp; </b>Comparativa    de herramientas para interacción de Haskell con lenguajes foráneos.</font></p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>3.  HaXml: Tecnología Haskell    para XML</b></font></p>     <p align="justify"><font size="2" face="Verdana">HaXml [8] es una librería implementada    en Haskell que presenta dos formas de procesar XML en un lenguaje funcional.</font></p>     <p align="justify"><font size="2" face="Verdana">La primera aprovecha la estructura    de árbol genérico de XML y la usa como base para crear un conjunto de filtros    y combinadores que permiten el procesamiento de su contenido. La segunda consiste    en transformar el contenido XML en un dato de Haskell y trabajar sobre este    tipo de dato algebraico.</font></p>     <p align="justify">&nbsp;</p> <h3 align="justify"><font size="2" face="Verdana">3.1. Los combinadores genéricos</font></h3>     <p align="justify"><font size="2" face="Verdana">Un documento XML es esencialmente    un árbol, tiene dos tipos: un elemento (encerrado en tags), y texto plano. El    elemento tiene un tag de inicio y un tag de terminación, además el tag de inicio    puede contener atributos en forma de pares nombre y valor. Entonces se puede    representar un documento XML usando el siguiente tipo de dato:</font></p>     <p align="left"><font size="2" face="Verdana"><b>data Element = Elem Name [Attribute]    [Content] </b></font></p>     <p align="left"><font face="Verdana"><b><font size="2">data Content = CElem Element        ]]></body>
<body><![CDATA[<br>        | CText String</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Los lenguajes funcionales son    muy buenos para procesar XML debido a su naturalidad para procesar tipos de    datos en forma de árbol.</font></p>     <p align="justify"><font size="2" face="Verdana">El tipo &#8217;content filter&#8217;    toma un fragmento del contenido XML y retorna una secuencia de contenido.</font></p>     <p align="left"><font size="2" face="Verdana"><b>type CFilter = Content -&gt;    [Content]</b></font></p>     <p align="justify"><font size="2" face="Verdana">En base a este tipo se puede    definir filtros básicos como filtros para selección, para predicados, y para    construcción de XML. por ejemplo podemos mencionar &#8217;elm&#8217; y &#8217;txt&#8217;,    el primero que sirve para filtrar el contenido XML siempre que sea un elemento,    y el segundo que filtra un texto plano como se observa en la siguiente definición:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>elm, es un elemento encerrado    en tags? </b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">txt, es texto?    <br>   :: CFilter</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Como pegamento para utilizar    los filtros se definen combinadores, éstos son operadores de alto orden que    sirven para componer funciones y construir a su vez combinadores más poderosos,    por ejemplo tenemos &#8217;o&#8217; que es la composición irlandesa que sirve    para conectar dos filtros entre si, el filtro de la izquierda es aplicado a    los resultados del filtro de la derecha, a continuación se presenta éste combinador    y otro de búsqueda recursiva:</font></p>     <p align="justify"><font size="2" face="Verdana">o, composición irlandesa</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana"><b>:: CFilter -&gt; CFilter -&gt;    CFilter</b></font></p>     <p align="justify"><font size="2" face="Verdana">deep, búsqueda recursiva (el    de más arriba) </font></p>     <p align="justify"><font size="2" face="Verdana"><b>:: CFilter -&gt; CFilter</b></font></p>     <p align="justify"><font size="2" face="Verdana">Usando los combinadores se obtiene    una forma de expresión más natural para el dominio de un problema, en este caso    los combinadores de HaXml dotan a Haskell de mayor expresividad para el procesamiento    de contenido XML.</font></p>     <p align="justify">&nbsp;</p> <h3 align="justify"><font size="2" face="Verdana">3.2. Transformación a tipos    de datos Haskell</font></h3>     <p align="justify"><font size="2" face="Verdana">Existe una correspondencia entre    el lenguaje que usado por DTDs para definir las reglas de XML y los tipos de    datos de Haskell.</font></p>     <p align="justify"><font size="2" face="Verdana">Para comprender mejor la forma    en que trabaja la transformación se presenta un ejemplo de DTD utilizado para    definir las reglas que debe cumplir un contenido XML que define una estructura    &#8216;persona&#8217; con sus &#8216;roles&#8217;:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>&lt;!DOCTYPE Persona     <br>   [&lt;!ELEMENT Persona (nombre, (rol*)) &gt;     <br>   &lt;!ELEMENT nombre (#PCDATA) &gt;     ]]></body>
<body><![CDATA[<br>   &lt;!ELEMENT rol (#PCDATA) &gt;    <br>        &lt;!ATTLIST parameter nombrerol CDATA #REQUIRED&gt;]&gt;</b></font></p>     <p align="justify"><font size="2" face="Verdana">Este DTD se transforma en el    siguiente tipo de dato algebraico de Haskell mediante la herramienta DtdToHaskell    de HaXml:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>...</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">data Persona = Persona    Nombre ([Rol])     <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">newtype Nombre = Nombre    String     <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">newtype Rol = Rol String    <br>   deriving (Eq,Show)</font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">data Parameter = Parameter    { parameterNombrerol :: String } deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Se puede hacer la lectura del    contenido XML y convertir el mismo en el tipo de dato Haskell usando la función    &#8217;readXml&#8217; de HaXml.</font></p>     <p align="justify"><font size="2" face="Verdana"><b>leerPersona:: String -&gt;    Maybe Persona </b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">leerPersona xmlMessage=    readXml xmlMessage</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Este enfoque de HaXml va más    allá de la simple comprobación de contenido XML bien formado, da lugar al concepto    de procesamiento válido de documentos, es decir un script que dado un documento    válido como entrada devuelve otro documento válido como resultado. Como la correspondencia    entre el DTD y el tipo de dato algebraico Haskell (generado a partir de éste)    es directa, el verificar que el contenido de un documento es válido como también    el script que lo procesa, se reduce a inferencia de tipos de Haskell.</font></p>     <p align="justify">&nbsp;</p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>4.  HermesPC</b></font></p>     <p align="justify"><font size="2" face="Verdana">Si bien las tecnologías revisadas    con anterioridad en este artículo tienen como objetivo la interacción de Haskell    con otros lenguajes de programación, algunas de ellas tienen ciertos problemas    y otras ciertas debilidades.</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">La solución propuesta a este    problema de interoperabilidad es dividida en dos partes:</font></p>     <p align="justify"><font size="2" face="Verdana">1.&nbsp;&nbsp;Un protocolo basado    en XML para la invocación remota de funciones implementadas en Haskell (HermesProtocol).</font></p>     <p align="justify"><font size="2" face="Verdana">2.&nbsp;&nbsp;Un servidor de    funciones Haskell que provea la ejecución de las funciones procesando/respondiendo    a las peticiones hechas mediante HermesProtocol (HermesService).</font></p> <h3 align="justify">&nbsp;</h3> <h3 align="justify"><font size="2" face="Verdana">4.1. Protocolo para invocación    de funciones Haskell: HermesProtocol</font></h3>     <p align="justify"><font size="2" face="Verdana">Es necesario proveernos de un    mecanismo que nos permita invocar a las funciones implementadas en Haskell,    para esto definimos HermesProtocol, un protocolo basado en XML.</font></p>     <p align="justify"><font size="2" face="Verdana">El comportamiento que se quiere    soportar es hacer peticiones de funciones sin saber acerca de la operación requerida    o del que hace el requerimiento. Ésta es la motivación del patrón de diseño    &#8217;comando&#8217;[7] del mundo Orientado a Objetos. Este patrón permite    encapsular un requerimiento como un objeto, permitiendo de esta manera tener    clientes que expresen sus diferentes requerimientos mediante parámetros.</font></p>     <p align="justify"><font size="2" face="Verdana">Apoyándose en HaXML es muy fácil    implementar el protocolo, es tan simple como definir el DTD con la estructura    y generar el tipo de dato Haskell que soportará el contenido XML.</font></p>     <p align="justify"><font size="2" face="Verdana">El primer paso es definir la    estructura de nuestro HermesProtocol:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>&lt;!DOCTYPE HermesMessage        <br>   [&lt;!ELEMENT HermesMessage (key, operation, (parameter*|result*)) &gt;     <br>   &lt;!ELEMENT key (#PCDATA) &gt;    ]]></body>
<body><![CDATA[<br>   &lt;!ELEMENT operation (#PCDATA) &gt;     <br>   &lt;!ELEMENT parameter (#PCDATA) &gt;    <br>        &lt;!ATTLIST parameter name CDATA #REQUIRED&gt; &lt;!ELEMENT result (#PCDATA)    &gt;    <br>        &lt;!ATTLIST result name CDATA #REQUIRED&gt;]&gt;</b></font></p>     <p align="justify"><font size="2" face="Verdana">HermesMessage representa un mensaje    que expresa la invocación de una función Haskell o el resultado de dicha invocación.    El elemento &#8217;key&#8217; provee un mecanismo de seguridad (una llave encriptada    en MD5 y codificada en Base64) que permite validar el origen del mensaje, &#8217;operation&#8217;    es el identificador de la funcionalidad requerida, y dependiendo de si es un    requerimiento o un resultado tenemos los parámetros (&#8217;parameter&#8217;)    o los resultados (&#8217;result&#8217;).</font></p>     <p align="justify"><font size="2" face="Verdana">Seguidamente debemos generar    la estructura de nuestro protocolo como un tipo de dato algebraico de Haskell:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>...</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">data HermesMessage =    HermesMessage Key Operation    <br>   (OneOf2 [Parameter] [Result])     <br>   deriving (Eq,Show)</font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">newtype Key = Key String        <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">newtype Operation= Operation    String     <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">data Parameter =Parameter    Parameter_Attrs String     <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">data Parameter_Attrs    = Parameter_Attrs{ parameterName :: String }    <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">data Result = Result    Result_Attrs String     <br>   deriving (Eq,Show) </font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">data Result_Attrs =    Result_Attrs { resultName :: String}    <br>   deriving (Eq,Show)</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">Se eligió este enfoque de procesamiento    de XML de HaXml (en lugar de usar los combinadores genéricos), debido a que    un HermesMessage siempre debe llegar completo (caso contrario no sería un mensaje    correcto), lo cual nos obliga a obtener un documento válido como entrada para    poder generar otro documento válido como salida (procesamiento válido de documentos).</font></p>     <p align="justify"><font size="2" face="Verdana">Un ejemplo de un mensaje de HermesProtocol    se muestra en el siguiente listado:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>&lt;HermesMessage&gt;</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">&lt;key&gt;2sxdCynQpn0+YshcbE8XnQ==&lt;/key&gt;    </font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">&lt;operation&gt;VERIFY_RSS&lt;/operation&gt;</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">&lt;parameter name=&quot;FEED&quot;&gt;PD94bWwgdmVyc2lvbj0i...&lt;/parameter&gt;    </font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">&lt;/HermesMessage&gt;</font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify">&nbsp;</p> <h3 align="justify"><font size="2" face="Verdana">4.2. Servicios en Haskell: HermesService</font></h3>     <p align="justify"><font size="2" face="Verdana">Un enfoque muy apropiado para    el servidor de funciones Haskell es el uso de programación de redes, la comunicación    mediante protocolos de red es independiente del lenguaje de programación, solo    se necesita dos puntos que puedan comunicarse entre si usando un protocolo de    red para poder interactuar. Pero los protocolos de red (como TCP o UDP) están    orientados simplemente a la transmisión correcta de datos planos, razón por    la cual se tiene que apalancar este mecanismo de manera que se pueda transmitir    requerimientos de invocación de funciones, para eso usamos el HermesProtocol    definido en la anterior sección.</font></p>     <p align="justify"><font size="2" face="Verdana">Se puede observar el comportamiento    de HermesService en la <a href="#imagen1">Figura 1</a>.</font></p>     <p align="center"><font size="2" face="Verdana"><b>&nbsp;<a name="imagen1"></a>&nbsp;    </b> </font> <font size="2" face="Verdana"><img width=408 height=233 src="/img/revistas/ran/v5n3/v5n3a03-01.jpg"></font>      <p align="center"><font size="2" face="Verdana"><b>Figura 1:</b> HermesService</font></p> <font face="Verdana"></p></font> </font>     <p align="justify"><font size="2" face="Verdana">Dado que ya tenemos el tipo de    dato algebraico de Haskell que define la estructura de HermesProtocol, convertir    el contenido XML al tipo de dato se hace en unas pocas líneas de código:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>import Text.XML.HaXml.XML2Haskell    import Maybe</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">parseHermesMessage::    String -&gt; Maybe HermesMessage </font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">parseHermesMessage xmlMessage=    readXml xmlMessage</font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">El mensaje se lo recibe mediante    una conexión de red, esto creando un socket usando la librería Network de Ghc.</font></p>     <p align="justify"><font size="2" face="Verdana"><b>startHermesService=forever    (startService) startService=    <br>   do{(msg, socket, handle) &lt;- listenMessage portNumber; forkIO(processNetworkMessage    msg socket handle);}</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">where portNumber=5760</font></b></font></p>     <p align="justify"><font size="2" face="Verdana">La función &#8216;forkIO&#8217;    del módulo Concurrent de Ghc permite iniciar un nuevo hilo que procesa el requerimiento,    retorna el resultado (o un error si se diera el caso) y termina. Además que    &#8217;forever&#8217; proporciona un ciclo infinito que constantemente acepta    los requerimientos entrantes.</font></p>     <p align="justify"><font size="2" face="Verdana"><b>result &lt;- catch (processMessage    (parseHermesMessage message))    <br>   (return(createError &quot;ERROR&quot;));</b></font></p>     <p align="justify"><font size="2" face="Verdana">El resultado se lo retorna también    empaquetado en HermesProtocol (en la sección &#8217;result&#8217;), lo mismo    que los posibles errores.</font></p>     <p align="justify"><font size="2" face="Verdana">Toda esta lógica es muy similar    a la de los Servicios Web con SOAP, claro que mucho más simple y liviana.</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">La implementación realizada,    permite recibir requerimientos de funciones Haskell a través de un Socket de    red, seguidamente buscar la función referida por un identificador (operation),    ejecutar esta función pasándole como parámetros los contenidos en el mensaje    y finalmente retornar un resultado también empaquetado en el protocolo.</font></p>     <p align="justify"><font size="2" face="Verdana">La definición y consistencia    de tipos de datos de los parámetros son responsabilidad del desarrollador, aunque    el mecanismo debería extenderse en un futuro para poder hacer este manejo de    tipos de manera automática.</font></p>     <p align="justify">&nbsp;</p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>5.  Ejemplo: usando HermesPC    desde .Net</b></font></p>     <p align=center><font size="2" face="Verdana"><b><img width=441 height=313 id="Picture 4" src="/img/revistas/ran/v5n3/v5n3a03-02.jpg" alt=":paper:figura2.jpg"></b></font></p>     <p align="center"><font size="2" face="Verdana"><b>Figura 2:&nbsp;&nbsp; </b>Vista    de HermesRSS</font></p>     <p align="justify"><font size="2" face="Verdana">Para experimentar con la solución    propuesta (e implementada), se desarrolló una aplicación de complejidad promedio    con requerimientos de usuarios reales.</font></p>     <p align="justify"><font size="2" face="Verdana">HermesRss (nombre código) es    una aplicación web implementada con las tecnologías ASP.NET (en C#) y NHibernate,    que tiene como objetivo proporcionar las funciones de un agregador de formatos    de sindicación, es decir que permite a un usuario monitorear fuentes de redifusión    (en formatos rss y atom) de su interés.</font></p>     <p align="justify"><font size="2" face="Verdana">La aplicación implementa componentes    que presentan funcionalidades requeridas por un sistema de este tipo, tales    como administración de usuarios, manejo de fuentes de redifusión, administración    de carpetas, manejo de suscripciones y búsquedas en las mismas. En la <a href="#imagen3">Figura    3</a> se puede apreciar los componentes de la lógica del negocio de la aplicación.</font></p>     ]]></body>
<body><![CDATA[<p align=center><font size="2" face="Verdana"><a name="imagen3"></a><img width=262 height=438 id="Picture 5" src="/img/revistas/ran/v5n3/v5n3a03-03.jpg" alt="Work:Tesis:HermesDocument:diagrams:hermes_components_aqua.psd"></font></p>     <p align="center"><font size="2" face="Verdana"><b>Figura 3:&nbsp;&nbsp; </b>Diagrama    de componentes de HermesRss</font></p>     <p align="justify"><font size="2" face="Verdana">La solución de servicios Haskell,    simplemente provee los servicios de traducción de contenido XML en formatos    rss y atom a formato HTML. Esta funcionalidad es implementada con la ayuda de    HaXml que permite esta transformación de XML a HTML de manera liviana usando    los filtros y combinadores genéricos y los combinadores para generación de HTML    que tiene incluidos.</font></p>     <p align="justify"><font size="2" face="Verdana">HermesRss está implementado con    un enfoque orientado a componentes, debido a lo cual se implementó un componente    Procesador de fuentes de redifusión, el cual contiene un cliente de HermesService.    Este cliente se encarga de componer los mensajes que invocan las funciones Haskell    (funciones de traducción de formatos de sindicación); luego envía los mensajes    y procesa el resultado.</font></p>     <p align="justify"><font size="2" face="Verdana">Todo esto se hace tomando consideraciones    de seguridad pertinentes, es decir se genera una llave encriptada que luego    debe ser verificada en el lado Haskell y viceversa, se puede ver esto en el    siguiente listado que contiene código C#:</font></p>     <p align="justify"><font size="2" face="Verdana"><b>string encryptedKey = generateKey(&quot;...&quot;);    //genera llave</b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">Communications comm=new    Communications(); </font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">comm.startConnection(server,portNumber);</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">string message=createHermesServiceMessage(encryptedKey,    operation, parameters); //compone el mensaje</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">res=comm.transmitMessage(message+&quot;\n&quot;);    //invoca función Haskell</font></b></font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">res = comm.readMessage();    //espera resultados</font></b></font></p>     <p align="justify"><font face="Verdana"><b><font size="2">...</font></b></font></p>     <p align="justify"><font size="2" face="Verdana"><b>comm.closeConnection();</b></font></p>     <p align="justify"><font size="2" face="Verdana">El procedimiento para consumir    un servicio Haskell es bastante sencillo, primero se debe generar la llave encriptada,    luego se inicia la comunicación con HermesService (mediante un Socket sobre    TCP), se compone el mensaje (con la operación requerida y los parámetros necesarios)    y se envía el mensaje. A continuación se espera, se procesa los resultados y    se cierra la comunicación.</font></p>     <p align="justify"><font size="2" face="Verdana">Este comportamiento es posible    desde cualquier lenguaje de programación que soporte comunicación de redes y    procesamiento de contenido XML, este es uno de los mayores beneficios de HermesPC,    de hecho el HermesService jamás se entera con qué lenguaje o plataforma está    interactuando.</font></p>     <p align="justify">&nbsp;</p>     <p align="justify">&nbsp;</p>     <p align="justify"><font size="3" face="Verdana"><b>6.  Conclusión</b></font></p>     <p align="justify"><font size="2" face="Verdana">XML es un lenguaje muy potente    para representar información estructurada, además que es una especificación,    es decir que no está ligada a ninguna plataforma en particular, sino que puede    ser procesado desde cualquier lenguaje de programación que tenga capacidades    básicas (es prácticamente una funcionalidad por defecto en los lenguajes de    programación actuales).</font></p>     ]]></body>
<body><![CDATA[<p align="justify"><font size="2" face="Verdana">El uso de XML también permite    aprovechar las capacidades naturales de Haskell para procesar información estructurada    en forma de árboles con HaXml.</font></p>     <p align="justify"><font size="2" face="Verdana">Lo anterior hace que se opte    por utilizarlo para diseñar un protocolo que sirva para transmitir requerimientos    de invocación de funciones y procesar sus resultados, esto a través de tecnología    de red, lo cual mantiene consistencia con la intención de no ligar la solución    a algún lenguaje de programación o plataforma en particular.</font></p>     <p align="justify"><font size="2" face="Verdana">HermesProtocol, si bien es un    protocolo bastante simple, cuenta con todo el potencial para poder realizar    las invocaciones remotas a funciones de Haskell de una manera bastante transparente    a la plataforma, además que es bastante simple de usar al momento de desarrollar    y no crea complejidad innecesaria.</font></p>     <p align="justify"><font size="2" face="Verdana">HermesService por su parte, hace    un procesamiento de HermesProtocol bastante natural, debido al gran soporte    que presta HaXml y todas las funcionalidades provistas por los módulos de Ghc.</font></p>     <p align="justify"><font size="2" face="Verdana">A continuación se presenta una    tabla comparativa que muestras algunas diferencias con las soluciones investigadas    con anterioridad:</font></p>     <p align=center><font size="2" face="Verdana"><img width=702 height=188 src="/img/revistas/ran/v5n3/v5n3a03-t02.jpg"></font></p>     <p align="center"><font size="2" face="Verdana"><b>Tabla 2:&nbsp;&nbsp; </b>Comparativa    de las soluciones estudiadas con HermesPC</font></p>     <p align="justify"><font size="2" face="Verdana">El software en el que se puso    a prueba la solución propuesta es una aplicación web de la vida real, un sistema    pensado para usuarios reales que requieren de soluciones a sus requerimientos,    este caso de uso pone a prueba el comportamiento de la solución planteada, y    da resultados satisfactorios (se pudieron  implementar las funcionalidades requeridas    mediante HermesPC).</font></p>     <p align="justify"><font size="2" face="Verdana">Finalmente esto es un ejemplo    del gran potencial que tiene Haskell dentro del desarrollo de aplicaciones del    mundo real, y desmitifica de cierta manera su alcance, demostrando que puede    ser empleado para resolver problemas que se hallan dentro un amplio dominio    de aplicaciones, además que de esta manera se quiere animar a más desarrolladores    a poder probar los beneficios de la Programación Funcional.</font></p>     <p align="justify">&nbsp;</p>     ]]></body>
<body><![CDATA[<p align="justify">&nbsp;</p> <hr align="center" noshade>     <p align="justify"><font size="3" face="Verdana"><b>Referencias</b></font></p>     <!-- ref --><p align="justify"><font size="2" face="Verdana">[1]&nbsp;&nbsp;Chakravarty M.    et al The Haskell 98 Foreign Function Interface 1.0 An Addendum to the Haskell    98 Report. 2002..2003.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773369&pid=S1683-0789201200010000300001&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[2]&nbsp;&nbsp;Finne S. Hugs98    for .Net. 2002-2003.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773370&pid=S1683-0789201200010000300002&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[3]&nbsp;&nbsp;Finne S. et al    H/Direct: A Binary Foreign Language Interface for Haskell. 1998.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773371&pid=S1683-0789201200010000300003&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[4]&nbsp;&nbsp;Finne S. HaskellDirect    User&#8217;s Manual. 1999.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773372&pid=S1683-0789201200010000300004&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[5]&nbsp;&nbsp;Alarcón B., Lucas    S. Integración de componentes Haskell en .NET. 2005.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773373&pid=S1683-0789201200010000300005&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[6]&nbsp;&nbsp;Alarcón B., Lucas    S. Building .NET GUIs for Haskell applications. 2006.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773374&pid=S1683-0789201200010000300006&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[7]&nbsp;&nbsp;Gamma E., Helm    R., Johnson R., Vlissides J. Design Patterns - Elements of reusable Object-Oriented    Software. Addison-Wesley, 1995.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773375&pid=S1683-0789201200010000300007&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[8]&nbsp;&nbsp;Wallace M., Runciman    C. Haskell and XML: Generic Combinators or Type-Based Translation?. 1999.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773376&pid=S1683-0789201200010000300008&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><!-- ref --><p align="justify"><font size="2" face="Verdana">[9]&nbsp;&nbsp;Peyton Jones S.    Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and    foreign-language calls in Haskell. 2005.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=773377&pid=S1683-0789201200010000300009&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --><p align="justify"><font size="2" face="Verdana"><a name="ref1"></a>[1] Microsoft    Intermediate Language, lenguaje intermedio de la plataforma .Net</font></p>       ]]></body><back>
<ref-list>
<ref id="B1">
<label>1</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Chakravarty]]></surname>
<given-names><![CDATA[M.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[The Haskell 98 Foreign Function Interface 1.0 An Addendum to the Haskell 98 Report]]></article-title>
<source><![CDATA[]]></source>
<year></year>
</nlm-citation>
</ref>
<ref id="B2">
<label>2</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Finne]]></surname>
<given-names><![CDATA[S.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Hugs98 for .Net.]]></article-title>
<source><![CDATA[]]></source>
<year></year>
</nlm-citation>
</ref>
<ref id="B3">
<label>3</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Finne]]></surname>
<given-names><![CDATA[S.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[H/Direct: A Binary Foreign Language Interface for Haskell]]></article-title>
<source><![CDATA[]]></source>
<year>1998</year>
</nlm-citation>
</ref>
<ref id="B4">
<label>4</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Finne]]></surname>
<given-names><![CDATA[S.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[HaskellDirect User’s Manual.]]></article-title>
<source><![CDATA[]]></source>
<year>1999</year>
</nlm-citation>
</ref>
<ref id="B5">
<label>5</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Alarcón]]></surname>
<given-names><![CDATA[B.]]></given-names>
</name>
<name>
<surname><![CDATA[Lucas]]></surname>
<given-names><![CDATA[S.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Integración de componentes Haskell en .NET.]]></article-title>
<source><![CDATA[]]></source>
<year>2005</year>
</nlm-citation>
</ref>
<ref id="B6">
<label>6</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Alarcón]]></surname>
<given-names><![CDATA[B.]]></given-names>
</name>
<name>
<surname><![CDATA[Lucas]]></surname>
<given-names><![CDATA[S]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Building .NET GUIs for Haskell applications.]]></article-title>
<source><![CDATA[]]></source>
<year>2006</year>
</nlm-citation>
</ref>
<ref id="B7">
<label>7</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Gamma]]></surname>
<given-names><![CDATA[E.]]></given-names>
</name>
<name>
<surname><![CDATA[Helm]]></surname>
<given-names><![CDATA[R.]]></given-names>
</name>
<name>
<surname><![CDATA[Johnson]]></surname>
<given-names><![CDATA[R.]]></given-names>
</name>
<name>
<surname><![CDATA[Vlissides]]></surname>
<given-names><![CDATA[J.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Design Patterns - Elements of reusable Object-Oriented Software]]></article-title>
<source><![CDATA[]]></source>
<year>1995</year>
</nlm-citation>
</ref>
<ref id="B8">
<label>8</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Wallace]]></surname>
<given-names><![CDATA[M.]]></given-names>
</name>
<name>
<surname><![CDATA[Runciman]]></surname>
<given-names><![CDATA[C.]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Haskell and XML: Generic Combinators or Type-Based Translation]]></article-title>
<source><![CDATA[]]></source>
<year>1999</year>
</nlm-citation>
</ref>
<ref id="B9">
<label>9</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Jones S.]]></surname>
<given-names><![CDATA[Peyton]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell.]]></article-title>
<source><![CDATA[]]></source>
<year>2005</year>
</nlm-citation>
</ref>
</ref-list>
</back>
</article>
