为什么 Hackage link 一个模块到不同的源文件?

Why does Hackage link a module to a different source file?

我正在尝试理解 Hackage 显示的基本包的结构。 https://en.wikibooks.org/wiki/Haskell/Modules 之后的模块名称必须反映其来源的路径;引用以上内容:

The name of the file is the name of the module plus the .hs file extension. Any dots '.' in the module name are changed for directories.

以Data.List为例,这让我相信路径下应该有一个源文件../Data/List.hs然后包含

module Data.List where ...

(模导出列表)。

另一方面,如果我浏览 Hackage 上的 Data.List 模块并点击“# Source”链接,我会被定向到各种不同模块的源文件。其中包括:GHC.Base、Data.OldList、Data.Foldable、GHC.List。

再说一遍,我本地安装的基础包明明有一个../Data/List.hi接口文件。

因此我的问题是: 如何解释这种差异? Hackage 上真正展示的是什么?

在此先感谢您对此事的任何见解!

可以重新导出从模块导入的名称。当发生这种情况时,haddock 会帮助您链接到名称的原始来源,而不是重新导出模块中的导入行;它遵循你的间接寻址。这就是你的情况。所以以(++)(黑线鳕中第一个函数为Data.List)为例,代码结构如下:

 -- GHC/Base.hs
 module GHC.Base where
 (++) = ...

 -- Data/OldList.hs
 module Data.OldList ( (++) {- re-exports GHC.Base's (++) -}, ... ) where
 import GHC.Base -- brings (++) into scope

 -- Data/List.hs
 module Data.List ( (++), ... ) where
 import Data.OldList hiding ( ... {- does not mention (++) -} )

因此您可以看到黑线鳕实际上遵循了 两个 链接:(++) 是从 Data.OldList 导入的,甚至在那里它也是一个再导出。

编译器也会仔细跟踪定义名称的原始模块;如果您导入所有 Data.ListData.OldListGHC.Base,您会发现您仍然可以使用 (++),即使乍一看它看起来很模糊,好像它可能是模棱两可的您指的是 (Data.List.++)(Data.OldList.++)(GHC.Base.++) 中的哪一个。由于所有三个实际最终都解析为 (GHC.Base.++),因此没有歧义。