Haskell 迭代映射

Haskell 迭代映射,haskell,Haskell,我试图同时使用迭代和映射,但我被卡住了 我有一份可能的职位列表和一份初始职位: 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 take 8 $ iterate (ad

我试图同时使用
迭代
映射
,但我被卡住了

我有一份可能的职位列表和一份初始职位:

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
take 8 $ iterate (addTupple (0,1)) initpos
产生预期的:

[(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)

这里可以使用的是:它连接通过应用函数获得的列表。因此:

concatMap (\x -> (take 8 $ iterate (addTupple x) initpos)) legal
编辑

如果您不希望返回初始值(通过
迭代
),可以使用
tail
忽略列表的“head”:

concatMap (\x -> (take 8 $ tail $ iterate (addTupple x) initpos)) legal

这里有一种稍微不同的方式来看待这个问题——最终结果将与中的基本相同

让我们首先注意到,
iterate
是一个修改函数的函数——它将
a->a
函数转换为一个生成无限列表的函数:

iterate :: (a -> a) -> a -> [a]
既然如此,从

map (\move -> addTuple move initpos) legal
。。。使用
iterate
修改应用于
initpos
的函数

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

谢谢你的回答。我试图使用您的解决方案,但得到的
无法将预期类型“[b]”与实际类型“a0->[a0]”匹配可能的原因是:对太少的参数应用了“迭代”
并且
无法将类型“(Int,Int)”与“a0->a0”预期类型匹配:a0->a0实际类型:(Int,Int)可能原因:“AddTuple”应用于太多参数
您能再次提供帮助吗?干杯,高效!如果可以的话,我会投阿吉安的票。谢谢您知道初始pos是通过迭代返回的吗?关于您的P.S.,cf.非常有趣,谢谢!Cristal清楚的解释,我的经验使我能够获得您提到的无限列表列表,但我在
映射之前使用了
take 8
,这没有帮助。谢谢你抽出时间!由于
legal
中的元素是“移动方向”,因此输出不完全等于预期值。和
initpos
第一个元素。如果你运行它,我会得到
[(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(0,-1),…]
@WillemVanOnsem确实——这句话比我在一读问题时想到的更相关。答案作了相应的调整。
concatMap (\move -> (take 8 . iterate (addTuple move)) initpos) legal