如何检查隐藏的 HashMap.Base 类型?

How can I inspect a hidden HashMap.Base type?

我正在做一个引用 unordered-containers-0.2.8.0:Data.HashMap.Base.HashMap.

的项目

包含该类型值的模块在导入部分没有说明它来自哪里,我无法导入 Data.HashMap.Base

但是 :browsing 建议该类型至少在某些情况下是抽象的。

> :bro Data.HashMap.Lazy
[...]
unordered-containers-0.2.8.0:Data.HashMap.Base.toList ::
 unordered-containers-0.2.8.0:Data.HashMap.Base.HashMap k v
 -> [(k, v)]

这是否意味着我可以从 LazyStrict 变体导入函数?

是的,在 unordered-containers 包中,目的是导入 Data.HashMap.LazyData.HashMap.Strict。两种变体都有严格的键(评估为 WHNF),并且在值是否也评估为 WHNF 方面有所不同。

unordered-containers 的源代码包中,有一个隐藏模块 Data.HashMap.Base,其中包含惰性和严格变体共享的代码。因为这个模块是隐藏的(从技术上讲,因为它在 other-modules 节而不是 exposed-modules 节下的包的 Cabal 文件中列出),它不打算直接导入,而只能通过一个间接导入其他两个模块。

特别是对于 toList,公开的模块 Data.HashMap.LazyData.HashMap.Strict 都使用(即重新导出)隐藏模块中定义的 toList 的相同定义模块 Data.HashMap.Base,这就是您在 GHCI 浏览器中看到此内容的原因。

如果您在 GHCI 中导入模块之一,那么您应该能够检查 toList 及其组件类型:

> import Data.HashMap.Strict
> :t toList
toList :: HashMap k v -> [(k, v)]
> :i HashMap
type role HashMap nominal representational
data HashMap k v
  = unordered-containers-0.2.7.2:Data.HashMap.Base.Empty
  ...

事实上,您会发现相同的 HashMap 定义用于严格和惰性变体,因此它不是您所想的那种 "abstract" 类型:两种实现使用相同的底层具体数据结构,不同之处在于操作该数据结构的函数如何使用它。

顺便说一下,Data.Map.StrictData.Map.Lazy 普通地图也是如此。 "strict" 映射可以用于惰性操作,反之亦然,因为 "strict" 和 "lazy" 映射是同一个对象。引用 Data.Map.Lazy:

的文档

API of this module is strict in the keys, but lazy in the values. If you need value-strict maps, use Data.Map.Strict instead. The Map type itself is shared between the lazy and strict modules, meaning that the same Map value can be passed to functions in both modules (although that is rarely needed).