微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在预定义的访问者模式迭代器中提取/累积结果的“Haskell 方式”

如何解决在预定义的访问者模式迭代器中提取/累积结果的“Haskell 方式”

我开始使用 Haskell(来自多年的 C 和 C++)并决定尝试一个小型数据库项目。我将预定义的绑定库用于 C 数据库库 (Database.kyotocabint)。由于使用预定义方法时的效果分离,我正在努力弄清楚如何使用迭代器接口执行任何操作。

迭代数据库并将其打印出来(效果很好)的玩具演示是

test7 = do
  db <- openTree "testdatabase/mydb.kct" defaultLoggingOptions (Writer [] [])
  
  let visitor = \k v -> putStr (show k) >> putStr ":" >> putStrLn (show v) >> 
                        return (Left NoOperation)
  iterate db visitor False
  
  close db

iterate 和visitor 是由库绑定提供的,相关类型是

iterate :: forall db. WithDB db => db -> VisitorFull -> Writable -> IO ()
visitor :: ByteString -> ByteString -> IO (Either VisitorAction b)

但我不知道如何从迭代器内部提取信息而不是单独处理每个信息 - 例如收集列表中以 'a' 开头的所有键,甚至只计算条目数。

>

我是否受到限制,因为 iterate 仅具有 IO () 类型,因此我无法构建副作用并且必须重建它以替换库版本?纸上的状态 monad 似乎解决了这个问题,但访问者类型似乎不允许我在后续访问者调用中保持状态。

Haskell 解决这个问题的方法是什么?

马修

编辑 - 非常感谢下面的明确答案,其中 siad 0 它不是 Haskell 方式,但也提供了一个解决方案 - 这个答案让我找到了 Mutable objects,我找到了对选项的清晰解释。

解决方法

很遗憾,kyotocabinet 库似乎不支持您的操作。除了 iterate,它应该公开一些类似的操作,返回比 IO () 更复杂的东西,比如 IO aIO [a],同时需要更复杂的 visitor 函数。

不过,由于我们在 IO 内部工作,因此有一个解决方法:我们可以利用 IORef 并收集结果。不过,我想强调的是,这不是人们会用 Haskell 编写的惯用代码,但是由于这个库的限制,人们不得不使用一些东西。

无论如何,代码看起来像这样(未经测试):

test7 = do
  db <- openTree "testdatabase/mydb.kct" defaultLoggingOptions (Writer [] [])
  w <- newIORef []   -- create mutable var,initialize to []
  let visitor = \k v -> do
         putStrLn (show k ++ ":" ++ show v)
         modifyIORef w ((k,v):)  -- prepend (k,v) to the list w
         return (Left NoOperation)
  iterate db visitor False
  result <- readIORef w   -- get the whole list
  print result
  
  close db

由于您来自 C++,您可能想将上面的代码与以下伪 C++ 进行比较:

std::vector<std::pair<int,int>> w;
db.iterate([&](int k,int v) {
   std::cout << k << "," << v << "\n";
   w.push_back({k,v});
});
// here we can read w,even if db.iterate returns void

再说一次,这不是我认为惯用的 Haskell。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?