此功能有效:
serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))
但是当我搭便车时:
serialExpansion :: Int -> Map
serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))
我收到错误:
simplifier.hs:46:26: Not in scope: type constructor or class `Map'
我该如何宣布这个功能?
答案 0 :(得分:12)
Map
是参数化数据类型(也称为abstract data type)。只有在为键指定类型并为值指定类型时,才能获得完全定义的类型。
例如,允许您按String
查找Integer
的地图的类型为Map Integer String
。
此外,您似乎已导入Map限定(如您所愿)。因此,您必须在签名中使用Map.Map
而不是Map
。
因此,您的函数应该具有类似
的签名 serialExpansion :: Int -> Map.Map Key Value
其中Key
是关键数据类型,Value
是值数据类型。在您的情况下,如果我猜测,也许您希望Int
和Key
都Value
。确切地说:您希望Key
与列表listOfSimpleDividers num
中的元素类型相同,并且Value
与列表中元素的类型相同{ {1}}。 (如果不清楚,可能有助于检查powers num
的类型签名。)
到现在为止你可能会问:“但是如果你能告诉Map.fromList
的正确返回类型,为什么编译器不能呢?”它可以。这正是你的第一个例子工作的原因。由于您省略了类型签名,因此编译器会从上下文中推断出它。正如您刚才所经历的那样,编写类型签名可以是确保您完全理解代码的好方法(而不是依赖于类型推断)。
答案 1 :(得分:8)
补充gspr的答案有两点:
通常的做法是导入类型构造函数Map
不合格,然后导入合格的其余模块:
import Data.Map (Map)
import qualified Data.Map as Map
这使您可以避免在所有类型的签名中写Map.Map
。
此外,在GHCi或Hugs中,您可以使用:t
向交互式环境询问任何函数的推断类型。例如,如果我在GHCi中加载此文件:
import Data.Map (Map)
import qualified Data.Map as Map
serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))
where
powers = undefined
listOfSimpleDividers = undefined
我得到以下内容:
*Main> :t serialExpansion
serialExpansion :: (Ord k) => t -> Map k a
如果您插入自己的powers
和listOfSimpleDividers
定义,则会获得更具体的类型。
答案 2 :(得分:0)
我只是希望得到一张没有任何内容的地图,然后以更灵活的方式添加它。
如果你想做类似的事情,你需要Map.empty
(假设你已经导入了它)。