c++ - 使用 O(1) 元素访问在 Haskell 中实现高效的类似 zipper 的数据结构

标签 c++ performance algorithm haskell zipper

问题

我想创建一个数据类型,允许快速访问和修改其元素。是否可以在 Haskell 中创建一个结构和函数,其执行速度与简单的 C++ 实现一样快?

问题详情

我正在用 Haskell 编写一个编译器。我有 AST由数据类型表示,让我们考虑以下一个:

import Prelude hiding (id)

-- this is a sample data type, the real one has got a lot of constructors
data AST = A { id :: Int, x :: AST, y :: AST, z :: AST }
         | B { id :: Int }
         | C { id :: Int, x :: AST, y :: AST }
         | D { id :: Int, u :: AST, v :: AST, w :: AST}

每个 AST 节点都有一个唯一的标识符。我很乐意在 Haskell 中实现以下功能:

  • 一个函数getById,它将在O(1) 时间复杂度内返回一个选择id 的AST 节点。
  • 能够在结构上创建“焦点”并独立修改焦点元素。所以我希望能够记住一些子树上的焦点,并能够在 O(1) 时间复杂度内修改每个这样的焦点。

我在想Zippers , 但它们存在 3 个问题:

  1. 它们(据我所知)用于简单的数据类型,如二叉树,我们可以说,我们选择“左”或“右”分支。是否有任何简单的方法可以将它们用于上述复杂数据类型?
  2. 我认为他们不会允许我以 O(1) 时间复杂度实现 getById 函数,对吗?
  3. 我认为使用 Zippers 不可能创建一些独立的焦点。我所说的独立焦点是指焦点,它允许我们修改数据类型的不同部分,而无需重新计算其他焦点(在 O(1) 中)。

C++ 的思维方式

在 C++ 中,我们可以创建指向 AST 节点 nodePtrs 的指针数组。 nodeById 函数将在 O(1) 中执行,只需访问 *(nodePtrs[id])。因为 C++ 结构是可变的,我们可以在 O(1) 中不受任何限制地修改它的元素。

最佳答案

我认为 zipper 实际上总是可以得到的,你听说过differentiation吗? ?

嗯,关于 getById,我不确定这是个好主意。你可能想要一个像 getById::Int -> IO AST 这样的 Haskell 函数,它在数组或其他东西中使用查找。但是由于您稍后希望能够修改值(至少在概念上),您希望 getById 返回新修改的 AST 值还是第一个存储的 AST 值?这一切都变得有问题。看看您是否可以删除您的 haskell 版本的 ID 可能是个好主意。

我认为您的重点听起来是可行的。如果我们说 ZAST 是 AST 的 zipper 数据类型。那么你也许可以有类似的东西。

makeFocus :: ZAST -> Focus ZAST

type Focus =
  (ZAST -> ZAST) -> -- The modifier of the "below part"
  ZAST ->           -- The new "above part", you have to provide it again as it might have changed
  ZAST              -- The Result

但是,是的,它确实不如 C++ 方式方便。


总而言之,我认为您应该退后一步,看看您实际尝试做的事情(AST 优化、发出程序集等)是否可以使用不可变数据结构有效地完成。而不是全神贯注地尝试在 Haskell 中实现可变 C++ 数据结构的相同规范。

关于c++ - 使用 O(1) 元素访问在 Haskell 中实现高效的类似 zipper 的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20184355/

相关文章:

c++ - 如何实现平滑的声音衰减效果?

c++ - 什么决定了堆内存的分配位置?

algorithm - 具有所有相同元素的最长子数组的长度

C# 代码大小和代码执行时间

algorithm - 了解涉及生成器的递归函数

python - 删除表达式树中第一个元素及其在 Python 中的每个子表达式树中的括号

c++ - SFML平台碰撞

c++ - OpenMP 代码大部分时间都在等待 Join Barrier

MySQL 递增值与插入

Powershell - 提取事件查看器日志的有效方法