Estoy aprendiendo Haskell después de años de OOP.¿Cómo diseñar una "araña web" con estado en Haskell?
Estoy escribiendo una araña web muda con pocas funciones y estado.
No estoy seguro de cómo hacerlo bien en el mundo de FP.
En el mundo POO esta araña se podría diseñar como esto (por el uso):
Browser b = new Browser()
b.goto(“http://www.google.com/”)
String firstLink = b.getLinks()[0]
b.goto(firstLink)
print(b.getHtml())
Este código carga http://www.google.com/, a continuación, haga “clic” el primer eslabón, se carga el contenido de la segunda página y luego imprime el contenido.
class Browser {
goto(url: String) : void // loads HTML from given URL, blocking
getUrl() : String // returns current URL
getHtml() : String // returns current HTML
getLinks(): [String] // parses current HTML and returns a list of available links (URLs)
private _currentUrl:String
private _currentHtml:String
}
Es possbile tener 2 o “navegadores” a la vez, con su propio estado independiente:
Browser b1 = new Browser()
Browser b2 = new Browser()
b1.goto(“http://www.google.com/”)
b2.goto(“http://www.stackoverflow.com/”)
print(b1.getHtml())
print(b2.getHtml())
PREGUNTA: mostrar cómo diseñaría una cosa así en Haskell de scracth (Navegador -like API con posibilidad de tener varias instancias independientes)? Por favor, da un fragmento de código.
NOTA: Para simplificar, omita los detalles de la función getLinks() (es trivial y no es interesante).
También vamos a suponer que hay una función API
getUrlContents :: String -> IO String
que abre la conexión HTTP y devuelve un código HTML para determinada URL.
ACTUALIZACIÓN: ¿por qué tener el estado (o puede ser que no)?
La API puede tener más funciones, no solo "resultados de carga y análisis".
No los agregué para evitar la complejidad.
También podría importarle el encabezado HTTP Referer y las cookies enviándolas con cada solicitud para emular el comportamiento real del navegador.
cuenta la situación siguiente:
- abierto http://www.google.com/
- Tipo "Haskell" en la primera área de entrada
- botón Haga clic en "Búsqueda de Google"
- Haga clic en enlace de "2"
- Haga clic en enlace "3"
- Imprimir el HTML de la página actual (página de resultados de google 3 para "haskell")
Tener un escenario como este en las manos, yo como desarrollador gustaría transferirlo a codificar lo más cerca posible:
Browser b = new Browser()
b.goto("http://www.google.com/")
b.typeIntoInput(0, "haskell")
b.clickButton("Google Search") // b.goto(b.finButton("Google Search"))
b.clickLink("2") // b.goto(b.findLink("2"))
b.clickLink("3")
print(b.getHtml())
El objetivo de este escenario es conseguir HTML de la última página después de un conjunto de operaciones. Otro objetivo menos visible es mantener el código compacto.
Si el navegador tiene un estado, puede enviar el encabezado HTTP Referer y las cookies mientras oculta todas las mecánicas dentro de sí mismo y proporciona una buena API.
Si el navegador no tiene estado, es probable que el desarrollador pase todas las URL/HTML/Cookies actuales, y esto agrega ruido al código del escenario.
NOTA: Supongo que hay bibliotecas fuera para eliminar HTML en Haskell, pero mi intención no era eliminar HTML, pero aprenda cómo estas cosas en "caja negra" se pueden diseñar correctamente en Haskell.
Brillante. .... – oshyshko
Tenga en cuenta que la mónada BrowserAction ya existe: http://hackage.haskell.org/packages/archive/HTTP/4000.0.8/doc/html/Network-Browser.html – jrockway
También tenga en cuenta que 'flip mapM' se llama 'forM'. – BMeph