处理Haskell中出现的歧义



我正在导入Data.TextData.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,则需要为所有导入的标识符指定模块名称。

相关内容

  • 没有找到相关文章

最新更新