2010-12-06 91 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(假設你已經導入它合格)。