Data.Map实现中的错误?

时间:2012-06-24 19:28:11

标签: haskell containers monadfix tying-the-knot

我偶然发现了一些我猜测是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]。没什么大不了的。

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

当地图实施为Data.HashMap.Lazy(来自unordered-containers)时,此功能非常有用。但是,当实现是通常的Data.Map(来自containers)时,程序堆栈溢出 - 没有双关语意图 - Map无限尝试使用{{1来比较两个节点}}

所以我的问题是:这是(==)中的错误,还是我假设这些结构在Data.Map存在错误的情况下应该如何表现?

1 个答案:

答案 0 :(得分:22)

您的Ord实例不起作用:

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

对于有效的Ord实例,您必须定义compare(<=)。如果您只定义(<),则对compare(<=)的任何调用都将无限循环,因为两者都有默认的实现方式。 Ord的其他成员也是根据compare定义的,因此除了(<)之外什么都不会有效。