2011-09-29 54 views
1

我開始明白哈斯克爾的力量,如何延遲加載能的方式,如我如何懶洋洋地加載比列出其它數據類型在Haskell

main = do 
    s <- getContents 
    let r = map processIt (lines s) 
    putStr (unlines r) 

被利用,但我有麻煩的是擴展了其他數據類型的這種「在數據結構中說什麼,但在需要時獲取」的功能。

例如我有一個圖形類型。

type Key = String 
data Node = Node { key :: Key, links :: [Node] } 

我想寫作用於該圖(海峽正向搜索算法),純代碼不管它是如何構建的,但我想節點來填補懶洋洋自己,當我得到他們。

我想我需要一種方法來指定圖中的內容以及如何填充它(某種遞歸定義),但我在查看方法時遇到了困難。 喜歡的東西

loadGraph :: Key -> Node 
loadGraph k = 
    let (key,edges) = getNodeAndEdgesFromInternetOrDatabase k in 
    Node key (map loadGraph edges) 

我覺得這是接近,但我不太清楚如何做到這一點。幫助和提示,將不勝感激。 (特別是像getNodeAndEdgesFromInternetOrDatabase類型的東西)

回答

3

懶惰IO通常使用unsafeInterleaveIO實現,它會延遲動作的副作用,直到其請求結果爲止。

對於你的例子,它會像這樣。

loadGraph :: Key -> IO Node 
loadGraph k = unsafeInterleaveIO $ do 
    (key, edges) <- getNodeAndEdgesFromInternetOrDatabase k 
    edges' <- mapM loadGraph edges 
    return (Node key edges') 

由於unsafeInterleaveIO被包裝在每次調用loadGraph,當你請評價它,這隻會加載子。

惰性IO被某些人所詬病,因爲它使得難以推斷副作用發生的順序。不過,我認爲對於您的應用來說,只要您仔細考慮實施getNodeAndEdgesFromInternetOrDatabase,這可能是合適的。

+0

您如何知道在評估節點時文件讀取指針的位置?即如果節點需要的順序與它們在文件中出現的順序不同,或者最後一個節點的評估是否強制所有先前節點進行評估,它是否工作? – pat

+0

@pat:這假定'getNodeAndEdgesFromInternetOrDatabase'不依賴於以任何特定的順序被調用,所以在文件的情況下,它必須從絕對偏移讀取。如果你想強制這些動作按順序執行,同時仍然保持懶惰,請查看[lazyio'包](http://hackage.haskell.org/package/lazyio),它爲你提供了一個monad來完成這個任務。 – hammar

+0

假設我們正在從一個文件中讀取圖表...... – pat