Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell模糊事件——如何避免?_Haskell_Map - Fatal编程技术网

Haskell模糊事件——如何避免?

Haskell模糊事件——如何避免?,haskell,map,Haskell,Map,我在GHCI中执行以下操作: :m + Data.Map let map = fromList [(1, 2)] lookup 1 map GHCI知道map是一个(map整数)。那么,为什么它声称Prelude.lookup和Data.Map.lookup之间存在歧义,而类型是明确的,我可以避免吗 <interactive>:1:0: Ambiguous occurrence `lookup' It could refer to either `Prelude.l

我在GHCI中执行以下操作:

:m + Data.Map
let map = fromList [(1, 2)]
lookup 1 map
GHCI知道map是一个(map整数)。那么,为什么它声称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
:1:0:
不明确的“查找”
它可以引用从Prelude导入的“Prelude.lookup”
或“Data.Map.lookup”,从Data.Map导入
>:t地图
映射:映射整数
>:t前奏曲
前奏曲查找::(等式a)=>a->[(a,b)]->可能是b
>:t Data.Map.lookup
Data.Map.lookup::(Ord k)=>k->MAPK a->可能是a

类型明显不同,但Haskell不允许临时重载名称,因此您只能选择一个不带前缀的
查找

典型的解决方案是导入
数据。Map
合格:

> import qualified Data.Map as Map
那么你可以说

> lookup 1 [(1,2), (3,4)]
Just 2
> Map.lookup 1 Map.empty
Nothing
通常,Haskell库要么避免重复使用前奏曲中的名称,要么重复使用一大堆名称
Data.Map
是第二种方法之一,作者希望您导入它

[编辑以包含ephemient的评论]

如果要使用不带前缀的
Data.Map.lookup
,则必须隐藏
Prelude.lookup
,因为它是隐式导入的,否则:

import Prelude hiding (lookup) 
import Data.Map (lookup)

这有点奇怪,但如果您使用
Data.Map.lookup
一大堆数据,并且您的数据结构都是地图,而不是Alist,则可能会很有用。

更一般的一点是,这一点一开始让我感到困惑——因此,让我重申并强调一下Nathan Sanders说过的话:

Haskell不允许临时重载名称

这在默认情况下是正确的,但一开始似乎出人意料地不明显。Haskell允许两种类型的:

  • 参数多态性,允许函数以结构相同、抽象的方式对任意类型进行操作
  • 即席多态性,它允许函数以结构上不同但语义上可能相同的方式对任何定义的类型集进行操作
参数多态性是Haskell和相关语言中的标准方法(并且在有选择的情况下是首选);ad-hoc多态性在大多数其他语言中都是标准的,其名称类似于“函数重载”,并且在实践中通常通过使用相同的名称编写多个函数来实现

Haskell中的特殊多态性是按类型类启用的,类型类要求使用所有关联的特殊多态函数定义类,并为重载解析使用的类型显式声明实例。在实例声明之外定义的函数永远不会是特别的多态函数,即使它们的类型非常不同,以至于引用是明确的

因此,当在不同的模块中定义多个具有相同名称的非类型类函数时,如果您尝试使用其中一个函数,则导入两个模块将导致错误。在这方面,
Data.List
Data.Map
Data.Set
的组合尤其令人震惊,因为
Data.List
的一部分是由序曲导出的,所以标准做法是(正如内森·桑德斯所说)要始终导入其他符合条件的文件。

使用说明书中的代码,这种情况随时都会发生。你总是可以给他们一个不同的名字。还要注意电子书中嵌入的unicode空格

sum2 []= 0 
sum2 (n:ns) = n + sum2 ns

这就是我想要的答案,+1。但我还有一个问题要问。那么,为什么所有这些
数据.List
数据.Set
等都没有“容器”类型类呢?或者如果有(如果我理解正确,这就是
Functor
typeclass)--那么,为什么为容器类型定义实例在库中不是那么普遍呢?@ulidtko:简短的答案是“因为它比听起来难”,长的答案不适合注释。在什么容器支持什么操作和元素类型的限制方面,有很多复杂的问题。查找有关
TypeFamilies
扩展的信息——容器API是一个激发灵感的例子。@ulidtko这可能会让您感兴趣: