首页 > 解决方案 > 在 Haskell 中处理模棱两可的事件

问题描述

我正在导入两者Data.TextData.List并且它们各自的find功能都崩溃了。

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,在这种情况下,自动使用findfromData.List吗?

标签: haskellmodule

解决方案


是这里使用的唯一解决方案Data.List.find (\a -> a == 5) my_list,还是合格的进口?

据我所知,是的,没有其他解决方案。

编译器不会尝试对这两个选项进行类型检查并使用使您的代码编译的选项。在最普遍的情况下,这可能会导致指数级的爆炸式增长。考虑,例如,

foo a1 a2 .... aN

其中每一个a1..aN都是从两个不同的模块导入的。尝试哪种组合类型检查原则上需要测试 2^N 个组合。

此外,程序员总是有可能打算使用模块中的标识符,但他们犯了一个错误并且代码没有进行类型检查。在这种情况下,来自另一个模块的相同标识符可能会改为类型检查,从而使代码编译但产生错误的结果。(我知道,这是一个相当人为的例子。)


请注意,如果在您的导入模块中您只需要使用两个finds 之一,您可以隐藏另一个:

import Data.Text hiding (find)
import Data.List

或者,您可以提供显式不相交的导入列表:

import Data.Text (pack)
import Data.List (find, zip)

如果你需要两个finds,你可以为模块提供一个更短的名称

import Data.Text as T
import Data.List as L

然后使用L.find. 除了双重导入的标识符之外,您不需要较短的模块名称。如果import qualified改为使用,则需要为所有导入的标识符指定模块名称。


推荐阅读