我正在导入Data.Text
和Data.List
以及它们各自的find
函数collapse。
import Data.Text
import Data.List
my_list = [4, 2, 4, 5, 6, 2, 6]
find (a -> a == 5) my_list
上述代码导致以下错误
Ambiguous occurrence ‘find’
It could refer to
either ‘Data.Text.find’, imported from ‘Data.Text’
or ‘Data.List.find’,
imported from ‘Data.List’
(and originally defined in ‘Data.Foldable’)
唯一的解决方案是在这里使用Data.List.find (a -> a == 5) my_list
,还是合格的导入?
让我印象深刻的是
Data.List.find (a -> a == 5) my_list
--> Just 5
Data.Text.find (a -> a == 5) my_list
--> error: Couldn't match expected type ‘Text’ with actual type ‘[Integer]’
从find
函数签名中,编译器显然能够理解Data.Text.find
不能与[Integer]
一起工作。难道他不能使用这些信息来决定使用find
的哪个实例,在这种情况下,从Data.List
自动使用find
吗?
在这里使用
Data.List.find (a -> a == 5) my_list
的唯一解决方案,还是合格的导入?
据我所知,是的,没有其他解决方案。
编译器不会尝试对这两个选项进行类型检查,而是使用使代码编译的选项。在最普遍的情况下,这可能会导致指数级的爆炸。例如,考虑
foo a1 a2 .... aN
其中a1
。。CCD_ 13是从两个不同的模块导入的。尝试原则上需要测试2^N个组合的组合类型检查。
此外,程序员总是有可能使用模块中的标识符,但他们犯了一个错误,代码没有进行类型检查。在这种情况下,来自另一个模块的相同标识符可能会进行类型检查,从而使代码编译,但产生错误的结果。(我知道,这是一个相当做作的例子。(
注意,如果在导入模块中只需要使用两个find
中的一个,则可以隐藏另一个:
import Data.Text hiding (find)
import Data.List
或者,您可以提供显式的不相交导入列表:
import Data.Text (pack)
import Data.List (find, zip)
如果您需要两个find
,您可以为模块提供一个较短的名称
import Data.Text as T
import Data.List as L
然后使用CCD_ 16来消除歧义。除了双重导入的标识符之外,您不需要较短的模块名称。如果使用import qualified
,则需要为所有导入的标识符指定模块名称。