[Haskell] Name clashes
名字
一个模块名是一系列用点号分隔的标识符。这些标识符首字母都是大写,点号两边没有空格。
一个qualified name由模块名.unqualifed name构成。
例子
-- A.hs
module A where -- 导出了A.f
f = 1
-- B.hs
module B where -- 导出了B.f
f = 2
-- C.hs
module C(A.f) where -- 导出了A.f
import A -- 导入了f, A.f
import B -- 导入了f, B.f
f = 3
-- D.hs
module D(A.f, B.f) where -- A.f与B.f的unqualifed name相同,但是引用的entity不同,报错
import A -- 导入了f, A.f
import B -- 导入了f, B.f
f = 4
-- E.hs
module E(A.f,C.f) where -- A.f与B.f的unqualifed name相同,引用的entity也相同,警告
import A -- 导入了f, A.f
import C -- 导入了f, C.f
f = 5
-- F.hs
module F where -- 导出了F.f
import A as G -- 导入了f, G.f
import B as G -- 导入了f, G.f
f = 6
(1)模块C中,import A和import B同时导入了f,但不会报错。
(2)模块C中,定义了自己的f,不会报错,并且可以使用C.f来引用。
(3)在模块C中使用f的时候,会报错:Ambiguous occurrence ‘f’,因为f可能引用了模块A中的f,或模块B中的f,或模块C自己的f。
(4)模块D使用(A.f, B.f),导出相同unqualifed name的不同entity,会报错:Conflicting exports for ‘f’。
(5)模块E使用(A.f, C.f),导出相同unqualifed name的同一个entity,会警告:f’ is exported by ‘C.f’ and ‘A.f’。
(6)模块F,将模块A中的f导入为G.f,将模块B中的f也导入为G.f,不会报错,但是在使用G.f时会报错:Ambiguous occurrence ‘G.f’。
总结
(1)导入时的名字冲突(不论是qualified name F.hs还是unqualified name C.hs),不会报错,但是使用这个有歧义的名字会报错。
(2)导出列表中的名字,去掉了模块名后得到unqualifed name,同名引用了不同的entity会报错(D.hs),同名引用了相同的entity会警告(E.hs)。
(3)模块中定义内部名字的时候,它是一个unqualifed name,但也会同时创建一个qualifed name(C.hs)。这个内部名字可能会与其他导入的unqualifed name冲突,但是不会报错,只会在引用这个unqualifed name的时候报错。