我开始理解Haskell的强大功能以及如何以诸如
之类的方式利用延迟加载main = do
s <- getContents
let r = map processIt (lines s)
putStr (unlines r)
但是我遇到的麻烦是扩展这种“先在数据结构中说什么,但在需要时获取它”的功能,用于其他数据类型。
例如,我有一个图表类型。
type Key = String
data Node = Node { key :: Key, links :: [Node] }
我想编写一个纯粹的代码,这个代码可以作用于这个图形(Strait正向搜索算法),无论它是如何构建的,但是当我到达它们时,我希望节点能够懒洋洋地填充它们。
我认为我需要一种方法来预先指定图中的内容以及如何填充它(某种递归定义)但我很难看到如何。 像
这样的东西loadGraph :: Key -> Node
loadGraph k =
let (key,edges) = getNodeAndEdgesFromInternetOrDatabase k in
Node key (map loadGraph edges)
我觉得这很接近,但我不太清楚该怎么做。帮助和提示将不胜感激。 (特别是像getNodeAndEdgesFromInternetOrDatabase类型的东西)
答案 0 :(得分:3)
懒惰IO通常使用unsafeInterleaveIO
实现,这会延迟IO
操作的副作用,直到需要它的结果。
对于你的例子,它会是这样的。
loadGraph :: Key -> IO Node
loadGraph k = unsafeInterleaveIO $ do
(key, edges) <- getNodeAndEdgesFromInternetOrDatabase k
edges' <- mapM loadGraph edges
return (Node key edges')
由于unsafeInterleaveIO
正在包含对loadGraph
的每次调用,因此当您尝试对其进行评估时,这只会加载该子图。
getNodeAndEdgesFromInternetOrDatabase
的方式时要小心。