如何从函数返回Data.Map

时间:2010-12-06 09:37:00

标签: haskell

此功能有效:

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'

我该如何宣布这个功能?

3 个答案:

答案 0 :(得分:12)

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

例如,允许您按String查找Integer的地图的类型为Map Integer String

此外,您似乎已导入Map限定(如您所愿)。因此,您必须在签名中使用Map.Map而不是Map

因此,您的函数应该具有类似

的签名
 serialExpansion :: Int -> Map.Map Key Value

其中Key是关键数据类型,Value是值数据类型。在您的情况下,如果我猜测,也许您希望IntKeyValue。确切地说:您希望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

如果您插入自己的powerslistOfSimpleDividers定义,则会获得更具体的类型。

答案 2 :(得分:0)

我只是希望得到一张没有任何内容的地图,然后以更灵活的方式添加它。

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