小编akb*_*der的帖子

懒惰的树与空间泄漏

我正在编写一个试图实现玩具XML处理器的程序.现在,程序应该读取描述文档结构的事件流(想想SAX)并且懒惰地构建相应的树.

事件由以下数据类型定义:

data Event = Open String
           | Close
Run Code Online (Sandbox Code Playgroud)

那么可能的输入是:

[Open "a", Open "b", Close, Open "c", Close, Close]
Run Code Online (Sandbox Code Playgroud)

这将对应于树:

  a
 / \
b   c
Run Code Online (Sandbox Code Playgroud)

我想以懒惰的方式生成树,因此它不需要在任何时候以完整的形式存在于内存中.但是,我当前的实现似乎存在空间泄漏,导致所有节点即使在不再需要时也会被保留.这是代码:

data Event = Open String
           | Close

data Tree a = Tree a (Trees a)

type Trees a = [Tree a]

data Node = Node String


trees [] = []
trees (Open x : es) =
    let (children, rest) = splitStream es
    in  (Tree (Node x) (trees children)) : (trees rest)

splitStream es = …
Run Code Online (Sandbox Code Playgroud)

haskell lazy-evaluation

10
推荐指数
2
解决办法
540
查看次数

嵌套屏蔽异步异常

我正在编写各种数据库库.它导出的基本功能如下:

withDatabase :: FilePath -> (DBHandle -> IO a) -> IO a
Run Code Online (Sandbox Code Playgroud)

它自动管理数据库句柄的生命周期.

在内部,withDatabase使用Control.Exception中bracket函数.

withDatabase path f = bracket (openDatabase path) closeDatabase f
Run Code Online (Sandbox Code Playgroud)

在我的具体情况下,openDatabase可能会执行一些重要的I/O,因此会长时间阻塞.出于这个原因,我想运行它的一部分异步异常unmasked.(简化)实施可以是:

openDatabase :: FilePath -> IO DBHandle
openDatabase path = mask $ \restore -> do
                      h <- openFile path ReadWriteMode
                      restore (doLongStuff h) `onException` (hClose h)
                      ...
                      return (DBHandle h)
Run Code Online (Sandbox Code Playgroud)

我不确定这段代码是否产生了我想要的效果.

让我们回顾一下withDatabase,这次取代bracket它的定义:

withDatabase path f = mask $ \restore -> do
  h <- openDatabase path …
Run Code Online (Sandbox Code Playgroud)

haskell asynchronous exception-handling exception

5
推荐指数
1
解决办法
316
查看次数