我是Haskell的新手,我需要定义一个空的Data.map,并使用insert函数并更新值,为其键分配一个“整数列表”(例如[1,2,3])。然后查找关键值。
到目前为止我尝试的是:
import qualified Data.Map
foo num =
let
my_map = Data.Map.empty
new_map = bar my_map num 1
in
Data.Map.lookup 1 new_map
bar my_map num c =
if c > num then my_map
else
Data.Map.insert c [c] my_map
bar my_map num c+1
此代码不起作用。
请问一个简单的例子吗?
答案 0 :(得分:20)
人们通常使用此样板导入Data.Map
模块:
import Data.Map (Map)
import qualified Data.Map as Map
这个想法是,由于模块中的许多名称与Prelude
和其他模块冲突,您希望将它们用作限定名称,但不能用于Map
类型本身。第二行中的as Map
位使您无需输入任何内容 - 您只需说Map.map
,Map.empty
等。
现在,构建地图最简单,最常用的方法是使用模块中的fromList
函数。这会从键/值对列表构建Map
:Map.fromList :: Ord k => [(k, v)] -> Map k v
。要构建这个键/值对列表,您可以使用Haskell列表处理函数的全部功能,如下例所示:
myMap :: Integer -> Map Integer [Integer]
myMap n = Map.fromList (map makePair [1..n])
where makePair x = (x, [x])
GHCI中的示例输出:
>>> myMap 3
fromList [(1,[1]),(2,[2]),(3,[3])]
请注意,Map
类型甚至会将自身打印为可重建它的fromList
调用。为什么?因为这个函数确实是构建Map
的最常用方法。
相比之下,你在代码中所做的是你正在尝试编写一个命令式循环,它一次一个地增加一个条目的初始空映射。 Haskell等价的循环是列表函数。在我的版本中,我使用了以下内容:
[1..n]
- 生成从1
到n
的整数列表。map
- 将函数应用于列表的每个元素。Map.fromList
- 从键/值对列表中构建Map
。为了进一步证明这一点,如果你看the source code for Map.fromList
,它实际上是使用列表折叠函数定义的。
我建议你:在解决Map
之前先研究清单和Data.List
模块。特别是:
foldr
函数 - 如何使用它,以及如何编写它。map
编写自己的filter
,find
和foldr
版本。答案 1 :(得分:8)
这是一个展示此功能的小程序:
module Main where
import qualified Data.Map as M
main = do
let emptyMap = M.empty
mapWithKeys = M.insert 5 "Four" emptyMap
mapWithKeys' = M.insert 5 "Five" mapWithKeys
putStrLn $ mapWithKeys' M.! 5
程序将使用键5插入“Four”,然后将值更新为“Five”,最后查找并打印出来。
答案 2 :(得分:1)
看看基地的Data.Map
。
虽然此程序包确实导出了创建地图的empty
,但使用
myMap = Data.Map.fromlist [(1,"hello"), (3,"goodbye")]
fromList
获取(键,值)元组列表,并创建一个映射。如果您知道构建时需要的所有键值对,那就是这样。
您可以使用(!)
或lookup
来访问元素
答案 3 :(得分:0)
您的代码表明您有一些误解。
import qualified Data.Map
foo num =
let
my_map = Data.Map.empty
new_map = bar my_map num 1
in
Data.Map.lookup 1 map
我看到您使用map
变量,但可能意味着new_map
。由于Haskell定义了一个名为map
的函数,编译器会告诉你一个类型错误。纯粹为了便于阅读,减少空白区域和添加类型签名有很大帮助。
-- foo takes an `Int` and produces a Maybe [Int].
foo :: Int -> Maybe [Int]
foo num =
let my_map = Data.Map.empty
new_map = bar my_map num 1
in Data.Map.lookup 1 new_map
现在让我们看看bar
:
bar my_map num c =
if c > num then my_map
else
Data.Map.insert c [c] my_map
bar my_map num c+1
这里有一些问题:
then
和else
关键字应位于同一列c+1
应该有圆括号let
绑定 - 这不是一个可变的地图,所以通过插入你实际上是用新值创建一个新的地图。所以:
bar :: Map Int [Int] -> Int -> Int -> Map Int [Int]
bar my_map num c =
if c > num
then my_map
else let my_new_map = Data.Map.insert c [c] my_map
in bar my_new_map num (c+1)