我赞同 Ingo 关于从更简单的事情开始的评论。不过,我会稍微详细地分解一些事情。
首先,我假设您已经安装了最新的Haskell Platform。在平台的网站上有a page with collected documentation for the libraries included with it。任何不在该页面中的库都需要您单独安装。
该平台确实包含Data.HashTable,因此您无需安装任何东西,但如果您查看the latest Platform's documentation on it,您会发现它已被弃用并且很快就会被删除。所以我不会使用那个模块。
Haskell 平台带有地图/字典数据结构的两个最流行的 Haskell 实现:
-
Data.Map。 (大部分文档都在Data.Map.Lazy 中。)这将映射实现为一种平衡搜索树,这意味着键需要是有序类型——实现Ord 类的类型。很多内置的 Haskell 类型已经实现了这个类,所以这可能是你最开始的选择。
-
Data.HashMap 模块层次结构,有两个变体; Data.HashMap.Lazy 将是一个很好的起点。这将映射实现为一种哈希表,因此键需要实现Hashable 类。此类较新且不如 Ord 受欢迎,因此您可能经常需要为您的键类型实现此类。
所以Data.Map 是更容易使用的类型。但是要有效地使用它,除了最基本的语言结构之外,您还需要了解一些东西:
- 如何在源文件中导入模块。
- 如何使用限定导入——
Data.Map 的函数名称与 Haskell 中的许多内置函数名称冲突,这需要一些特殊的语法。
- 如何将模块加载到 ghci 解释器中。
- 如何编译使用
Data.Map 所在的containers 库的项目(使用cabal 工具)。
一旦完成,构建映射的最简单方法是使用键/值对列表:
module MyModule where
import Data.Map (Map) -- This just imports the type name
import qualified Data.Map as Map -- Imports everything else, but with names
-- prefixed with "Map." (with the period).
-- Example: make a Map from a key/value pair
ages :: Map String Integer
ages = Map.fromList [("Joe", 35), ("Mary", 37), ("Irma", 16)]
关于如何使用地图的几个例子:
-- Example: look up somebody and return a message saying what their age is.
-- 'Nothing' means that the map didn't have the key.
findAge :: String -> String
findAge name = case Map.lookup name ages of
Nothing -> "I don't know the age of " ++ name ++ "."
Just age -> name ++ " is " ++ show age ++ " years old."
-- Example: make a map with one extra entry compared to `ages` above.
moreAges :: Map String Integer
moreAges = Map.insert "Steve" 23 ages
-- Example: union of two maps.
evenMoreAges :: Map String Integer
evenMoreAges = Map.union moreAges anotherMap
where anotherMap = Map.fromList [("Metuselah", 111), ("Anuq", 3)]