我在GHCI做以下事情:
:m + Data.Map
let map = fromList [(1, 2)]
lookup 1 map
Run Code Online (Sandbox Code Playgroud)
GHCI知道map是(Map Integer Integer).那么为什么它在Prelude.lookup和Data.Map.lookup之间声明模糊,当类型清楚时我可以避免吗?
<interactive>:1:0:
Ambiguous occurrence `lookup'
It could refer to either `Prelude.lookup', imported from Prelude
or `Data.Map.lookup', imported from Data.Map
> :t map
map :: Map Integer Integer
> :t Prelude.lookup
Prelude.lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
> :t Data.Map.lookup
Data.Map.lookup :: (Ord k) => k -> Map k a -> Maybe a
Run Code Online (Sandbox Code Playgroud)
Nat*_*ers 53
类型明显不同,但Haskell不允许临时重载名称,因此您只能选择一个lookup没有前缀的方法.
典型的解决方案是导入Data.Map合格的:
> import qualified Data.Map as Map
Run Code Online (Sandbox Code Playgroud)
然后你可以说
> lookup 1 [(1,2), (3,4)]
Just 2
> Map.lookup 1 Map.empty
Nothing
Run Code Online (Sandbox Code Playgroud)
通常,Haskell库要么避免重复使用Prelude中的名称,要么重新使用它们中的一大堆.Data.Map是第二个,作者希望你导入它合格.
[编辑包括ephemient的评论]
如果你想在Data.Map.lookup没有前缀的情况下使用,你必须隐藏,Prelude.lookup因为它是隐式导入的,否则:
import Prelude hiding (lookup)
import Data.Map (lookup)
Run Code Online (Sandbox Code Playgroud)
这Data.Map.lookup有点奇怪,但是如果你使用一大堆而你的数据结构都是地图,那么可能会很有用.
C. *_*ann 23
稍微更一般地说,这首先使我感到困惑 - 所以,让我重申并强调内森桑德斯所说的话:
Haskell不允许临时重载名称
默认情况下这是正确的,但最初看起来非常明显.Haskell允许两种样式的多态函数:
参数多态性是Haskell和相关语言中的标准(并且是首选的选择)方法; ad-hoc多态性是大多数其他语言的标准,通过诸如"函数重载"之类的名称,并且通常通过编写具有相同名称的多个函数来实现.
在Haskell中通过类型类启用Ad-hoc多态,这需要使用所有关联的ad-hoc多态函数定义类,并为重载解析使用的类型显式声明实例.在实例声明之外定义的函数永远不是ad-hoc多态的,即使它们的类型足够明显,引用也是明确的.
因此,当在不同模块中定义多个具有相同名称的非类型类函数时,如果尝试使用任一函数,则导入两个不合格的模块将导致错误.的组合Data.List,Data.Map以及Data.Set在这方面特别严重,而且由于部分Data.List由序曲输出,标准的做法是(弥敦道桑德斯说)总是导入其他合格.