我正在尝试一起使用iterate
和map
,但我被卡住了。
我列出了可能的职位和初始职位:
legal = [(0,1),(0,-1),(1,0),(-1,0)]
initpos = (1,1)
一个功能:
addTupple::(Int,Int)->(Int,Int)->(Int,Int)
addTupple (x1,y1) (x2,y2) = (x1+x2,y1+y2)
我能做到:
map (addTupple initpos) legal
产生预期的:
[(1,2),(1,0),(2,1),(0,1)]
我能做到:
take 8 $ iterate (addTupple (0,1)) initpos
导致:
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8)]
但是,如果我想组合map和iterate以获得以下结果,那该怎么办:
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,1),(1,0),(1,-1),(1,-2),(1,-3),(1,-4),(1,-5),(1,-6),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(1,1),(0,1),(-1,1),(-2,1),(-3,1),(-4,1),(-5,1),(-6,1)]
结果是:
l1 = take 8 $ iterate (addTupple (0,1)) initpos
l2 = take 8 $ iterate (addTupple (0,-1)) initpos
l3 = take 8 $ iterate (addTupple (1,0)) initpos
l4 = take 8 $ iterate (addTupple (-1,0)) initpos
l1 ++ l2 ++ l3 ++ l4
我无法理解。任何的想法?提前谢谢。
Ps:我也不明白为什么take 8 $ iterate
会返回初始pos (1,1)
答案 0 :(得分:3)
您可以在这里使用的是concatMap :: (a -> [b]) -> [a] -> [b]
:它连接通过应用该函数获得的列表。所以:
concatMap (\x -> (take 8 $ iterate (addTupple x) initpos)) legal
这里我们引入一个 lambda-expression ,它将x
的每个元素legal
映射到take 8 $ iterate (addTupple x initpos)
。然后将所有这些列表连接在一起。
Prelude> concatMap (\x -> (take 8 $ iterate (addTupple x) initpos)) legal
[(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,1),(1,0),(1,-1),(1,-2),(1,-3),(1,-4),(1,-5),(1,-6),(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(1,1),(0,1),(-1,1),(-2,1),(-3,1),(-4,1),(-5,1),(-6,1)]
修改强>
如果您不希望返回初始值(iterate
),则可以使用tail
忽略列表的“头部”:
concatMap (\x -> (take 8 $ tail $ iterate (addTupple x) initpos)) legal
这构造:
Prelude> concatMap (\x -> (take 8 $ tail $ iterate (addTupple x) initpos)) legal
[(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9),(1,0),(1,-1),(1,-2),(1,-3),(1,-4),(1,-5),(1,-6),(1,-7),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(0,1),(-1,1),(-2,1),(-3,1),(-4,1),(-5,1),(-6,1),(-7,1)]
答案 1 :(得分:3)
以下是查看问题的略有不同的方式 - 最终结果与Willem Van Onsem's answer中的结果基本相同。
让我们首先注意iterate
是一个修改函数的函数 - 它将a -> a
函数转换为生成无限列表的函数:
iterate :: (a -> a) -> a -> [a]
就是这样,从......开始。
map (\move -> addTuple move initpos) legal
...并使用initpos
...
iterate
的函数
map (\move -> (iterate (addTuple move)) initpos) legal
-- Alternatively: map (\move -> iterate (addTuple move) initpos) legal
...将为您提供无限列表的列表,legal
中每对一列。我们可以使用take 8
来减少无限列表......
map (\move -> (take 8 . iterate (addTuple move)) initpos) legal
-- Alternatively: map (\move -> take 8 $ iterate (addTuple move) initpos) legal
..并使用concat
展平有限列表的结果列表:
concat $ map (\move -> (take 8 . iterate (addTuple move)) initpos) legal
最后,鉴于concatMap
被定义为concat . map
,我们可以使用它代替此concat
/ map
组合:
concatMap (\move -> (take 8 . iterate (addTuple move)) initpos) legal