1

我正在研究一个引用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)]

这是否意味着我可以从其中一个Lazy或多个Strict变体中导入函数?

4

1 回答 1

4

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

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

toList特别是,暴露的模块和Data.HashMap.Lazy两者Data.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严格变体和惰性变体使用相同的定义,因此它不是您所想的“抽象”类型:两种实现都使用相同的底层具体数据结构,并且在在该数据结构上运行的函数使用它。

Data.Map.Strict顺便说一句,这对于Data.Map.Lazy普通地图也是如此。“严格”映射可以与惰性操作一起使用,反之亦然,因为“严格”和“惰性”映射是同一个对象。从文档中引用Data.Map.Lazy

该模块的 API 在键上是严格的,但在值上是惰性的。如果您需要严格值的映射,请改用 Data.Map.Strict。Map 类型本身在惰性和严格模块之间共享,这意味着可以将相同的 Map 值传递给两个模块中的函数(尽管很少需要)。

于 2017-06-11T16:12:49.423 回答