Ich lerne Haskell nach Jahren der OOP.Wie man eine "Netzspinne" mit Staat in Haskell entwirft?
Ich schreibe eine dumme Webspinne mit wenigen Funktionen und Zustand.
Ich bin mir nicht sicher, wie es in der FP-Welt richtig geht.
In OOP Welt könnte diese Spinne wie diese gestaltet werden (durch Nutzung):
Browser b = new Browser()
b.goto(“http://www.google.com/”)
String firstLink = b.getLinks()[0]
b.goto(firstLink)
print(b.getHtml())
Dieser Code lädt http://www.google.com/, dann „Klicks“ der erste Link, lädt Inhalt der zweiten Seite und druckt dann den Inhalt.
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 ist possbile 2 zu haben oder „Browser“ auf einmal, mit einem eigenen separaten Staat:
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())
FRAGE: zeigen, wie würden Sie eine Sache von scracth in Haskell so entwerfen (Browser -ähnliche API mit der Möglichkeit, mehrere unabhängige Instanzen zu haben)? Bitte geben Sie ein Code-Snippet.
HINWEIS: Aus Gründen der Einfachheit überspringen Sie die Details der Funktion getLinks() (es ist trivial und nicht interessant).
Auch nehmen wir an, es gibt eine API-Funktion
getUrlContents :: String -> IO String
, die HTTP-Verbindung öffnet sich und gibt einen HTML-Code für bestimmte URL.
UPDATE: Warum Zustand haben (oder auch nicht)?
Die API kann mehr Funktionen haben, nicht nur einzelne "Lade- und Parsergebnisse".
Ich habe sie nicht hinzugefügt, um Komplexität zu vermeiden.
Auch könnte es sich um HTTP Referer Header und Cookies kümmern, indem Sie sie mit jeder Anfrage senden, um echtes Browserverhalten zu emulieren.
sich das folgende Szenario:
- öffnen http://www.google.com/
- Type "Haskell" in die erste Eingabebereich
- Klicken Sie auf Schaltfläche "Google-Suche"
- Click link "2"
- Click Link "3"
- HTML der aktuellen Seite drucken (Google-Ergebnisseite 3 für "Haskell")
ein Szenario wie dieses auf den Händen zu haben, die ich als Entwickler möchte es übertragen so nah wie möglich zu kodieren:
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())
Das Ziel dieses Szenario HTML-Code der letzten Seite zu bekommen, ist nach eine Reihe von Operationen. Ein weiteres weniger sichtbares Ziel ist es, Code kompakt zu halten.
Wenn Browser einen Status hat, kann er HTTP Referer Header und Cookies senden, während er alle Mechaniken in sich versteckt und eine nette API gibt.
Wenn Browser keinen Status hat, wird der Entwickler wahrscheinlich alle aktuellen URL/HTML/Cookies weitergeben - und das fügt dem Szenario-Code Rauschen hinzu.
HINWEIS: Ich denke, es gibt Bibliotheken außerhalb für die Verschrottung von HTML in Haskell, aber meine Absicht war nicht, HTML zu verwerfen, sondern zu lernen, wie diese "black-boxed" Dinge in Haskell richtig gestaltet werden können.
Brilliant. .... – oshyshko
Beachten Sie, dass die BrowserAction-Monade bereits existiert: http://hackage.haskell.org/packages/archive/HTTP/4000.0.8/doc/html/Network-Browser.html – jrockway
Beachten Sie auch, dass 'flip mapM' heißt 'forM'. – BMeph