迭代和映射

时间:2017-04-15 16:39:47

标签: haskell

我正在尝试一起使用iteratemap,但我被卡住了。

我列出了可能的职位和初始职位:

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)

2 个答案:

答案 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