[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的时候报错。