【问题标题】:Bug in Data.Map implementation?Data.Map 实现中的错误?
【发布时间】:2012-06-26 04:33:12
【问题描述】:

我偶然发现了一些我猜测Data.Map 中的错误,但这也很可能是我的 Haskell 知识中的错误。希望有人能澄清它是什么:)

请参考this gist。我正在将循环链表结构序列化为字节流。对于任何给定的节点,格式为:

data Node = Node
  { val  :: Word8
  , next :: Node
  }

我希望它被序列化为一对字节:第一个字节代表val,第二个字节代表next 可以定位的字节流中的偏移量。例如,我期望:

let n0 = Node 0 n1
    n1 = Node 1 n0

被序列化为[0, 1, 1, 0]。没什么大不了的。

这里有点棘手的部分是我正在利用MonadFixRWST 实例来“打结”字节流偏移:我维护一个从节点到偏移的映射,在序列化期间填充映射,但也引用映射中在序列化完成之前不一定存在的条目。

当地图实现是Data.HashMap.Lazy(来自unordered-containers)时,这很有效。然而,当实现是通常的Data.Map(来自containers)时,程序堆栈溢出——没有双关语——Map 无限尝试使用(==) 比较两个节点。

所以我的问题是:这是Data.Map 中的一个错误,还是我对这些结构在mfix 存在时应该如何表现的假设有缺陷?

【问题讨论】:

  • @RomanCheplyaka 这取代了我之前删除的可怕帖子。你要求查看完整的代码,所以你去 :)
  • 另外,我刚刚发现(令我惊讶的是)Data.HashMap.Strict 也可以正常工作。
  • 现在你明白我为什么要求查看代码了;)

标签: haskell containers monadfix tying-the-knot


【解决方案1】:

您的 Ord 实例不起作用:

instance Ord Node where -- for use in Data.Map
  Node a _ < Node b _ = a < b

对于一个工作的Ord 实例,您必须定义compare(&lt;=)。如果您只定义(&lt;),任何对compare(&lt;=) 的调用都将无限循环,因为两者都具有彼此的默认实现。 Ord 的其他成员也是根据 compare 定义的,所以除了 (&lt;) 之外的任何东西都不会起作用。

【讨论】:

  • 该死,我是个白痴。我自己才意识到这一点。好在我在互联网上自作多情没有问题。
  • @mergeconflict 这没有什么可耻的!如果你不让自己尴尬,你就没有学习!
  • @GabrielGonzalez 阿门。我以教书为生,我经常告诉我的学生同样的话:)
  • @mergeconflict 很难把一个人教给自己的词应用到自己身上——我也教。
猜你喜欢
  • 1970-01-01
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 2022-08-20
相关资源
最近更新 更多