我在多年的面向對象方面學習Haskell。如何在Haskell中設計具有狀態的「web蜘蛛」?
我正在寫一個功能和狀態很少的啞蜘蛛。
我不知道如何在FP世界中做到這一點。
在OOP的世界這種蜘蛛可以這樣設計(用法):
Browser b = new Browser()
b.goto(「http://www.google.com/」)
String firstLink = b.getLinks()[0]
b.goto(firstLink)
print(b.getHtml())
此代碼加載http://www.google.com/,然後「點擊」的第一個環節,第二個頁面的加載內容,然後打印的內容。
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
}
這是possbile有2或「瀏覽器」一次,有自己獨立的狀態:
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())
問題:表明你將如何在Haskell從scracth設計這樣的事情(瀏覽器類似的API可能有幾個獨立的實例)?請給出一個代碼片段。
注意:爲了簡單起見,跳過getLinks()函數的細節(它的微不足道和不感興趣)。
也讓我們假設有打開HTTP連接,並返回給定的URL的HTML API函數
getUrlContents :: String -> IO String
。
UPDATE:爲什麼有狀態(或可能不)?
該API可以有更多的功能,而不僅僅是單一的「加載和解析結果」。
我沒有添加它們來避免複雜性。
此外,它可以通過向每個請求發送HTTP Referer頭和Cookie來模擬真實的瀏覽器行爲。
考慮以下情形:
- 打開http://www.google.com/
- 類型 「哈斯克爾」 爲第一輸入區域
- 點擊按鈕 「谷歌搜索」
- 點擊鏈接 「2」
- 點擊鏈接「3」
- 打印當前頁面的HTML(谷歌結果第3頁,用於「haskell」)
有動手這樣的情況下,我作爲一個開發者想轉讓其儘可能接近的代碼:
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())
此方案的目的是後能得到最後一頁的HTML一組操作。 另一個不太明顯的目標是保持代碼緊湊。
如果瀏覽器有一個狀態,它可以發送HTTP Referer頭和cookie,同時隱藏所有機制並提供良好的API。
如果瀏覽器沒有狀態,開發人員可能會傳遞所有當前的URL/HTML/Cookies - 這會給場景代碼增加噪音。
注意:我猜Haskell中存在用於報廢HTML的庫,但我的目的不是要廢除HTML,而是要了解如何在Haskell中正確設計這些「黑盒子」的東西。
輝煌。 ... – oshyshko 2010-02-22 00:37:40
請注意,BrowserAction monad已經存在:http://hackage.haskell.org/packages/archive/HTTP/4000.0.8/doc/html/Network-Browser.html – jrockway 2010-02-24 04:57:51
另請注意,'flip mapM'被稱爲'forM'。 – BMeph 2010-07-12 05:56:32