2010-12-06 58 views
6
返回Data.Map

此功能:如何从功能

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' 

我该怎么申报功能?

回答

12

Map是一个参数化数据类型(也称为abstract data type)。只有为键指定类型并为值指定类型时,才会得到完全定义的类型。

例如,可以通过Integer查找String s的地图s的类型为Map Integer String

此外,它似乎你已经导入地图限定(你应该)。因此,您必须在签名中使用Map.Map而不是Map

因此,你的函数应该有像

serialExpansion :: Int -> Map.Map Key Value 

的签名,其中Key的关键数据类型和Value是值的数据类型。在你的情况下,如果我猜测,也许你想IntKeyValue。准确地说:您希望Key与列表listOfSimpleDividers numValue中的元素的类型与列表powers num中元素的类型相同。 (如果不清楚,可能有助于检查Map.fromList的类型签名)。

现在您可能会问:“但是如果您能够告诉serialExpansion的正确返回类型,为什么编译器不能?”它可以。这正是你的第一个例子工作的原因。由于您省略了类型签名,因此编译器从上下文中推断出它。正如您刚刚所经历的那样,编写类型签名可以是确保您完全理解代码的一种好方法(而不是依赖于类型推断)。

+0

最后一段是关键! +1 – fuz 2010-12-06 10:05:07

7

两点补充GSPR的回答是:

这是一个常见的做法是导入类型构造Map不合格,然后导入模块的合格休息:

import Data.Map (Map) 
import qualified Data.Map as Map 

这可以让你避免编写Map.Map在你的类型签名无处不在。

此外,在GHCi或拥抱中,您可以使用: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你会得到一个更具体的类型。

0

我只是想找一张没有任何东西的地图,然后以更灵活的方式添加到地图中。

如果你想做类似的事情,你需要Map.empty(假设你已经导入它合格)。