我已经编写了一个函数来获取两点之间一条线的一定数量的坐标。
line :: Coord -> Coord -> [Coord]
line (xa,ya) (xb,yb) = ....
但是当我尝试使用它来获取多边形的所有坐标时,我遇到了一些困难。我输入的输入是顶点的坐标。
polygon :: [Coord] -> [Coord]
polygon (p1:p2:ps) = line p1 p2 : polygon ps
当我运行这个多边形时,我没有得到我想要获得的结果。 任何人都可以为此提供一些帮助吗?我知道如何为列表中的每个元素添加一个递归,但我不知道如何对两个元素使用递归。
所以,如果我给出一个列表顶点[p1,p2,p3,p4] 该函数应该返回[第p1行第2行:第p2行第3行:第p4行:第4行第4行] 如何使用递归来实现这个目标?
非常感谢。
答案 0 :(得分:2)
因此,如果我给出一个列表顶点
[p1, p2, p3, p4]
,该函数应该返回[line p1 p2 : line p2 p3 : line p3 p4 : line p4 p1]
你可能意味着
[line p1 p2, line p2 p3, line p3 p4, line p4 p1] :: [[Coord]]
或
line p1 p2 ++ line p2 p3 ++ line p3 p4 ++ line p4 p1 :: [Coord]
相当于
concat [line p1 p2, line p2 p3, line p3 p4, line p4 p1] :: [Coord]
您所描述的内容不会进行类型检查:[x : y : z]
是一个列表,其中包含一个列表x : y : z
,其中z
是尾部。但如果line px py
是此列表的元素,则它也不能是该列表的尾部。 [x, y, z]
也可以写为x : [y, z]
或x : y : [z]
或x : y : z : []
。这里的混淆源于使用x : ...
来构建带递归的列表,但固定长度的列表通常看起来像[x, y, z]
。
因为你两次使用每个点;一次作为line
的第一个参数,一次作为第二个参数,您可以使用以下递归模式:
polygon :: [Coord] -> [Coord]
polygon (p1:p2:ps) = line p1 p2 ++ polygon (p2:ps)
polygon [pLast] = ???
polygon [] = []
在第二次迭代中,曾经p2
的内容变为p1
,依此类推。
您可以手动评估此图片:
polygon (px : py : pz : [])
~> line px py ++ polygon (py : pz : [])
~> line px py ++ line py pz ++ polygon (pz : [])
~> line px py ++ line py pz ++ ???
不幸的是,似乎要将最后一个坐标连接到第一个坐标,您希望以某种方式编写line pLast pFirst
,但pFirst
不在范围内。 提示:您可以重写此功能,以便在到达列表末尾时可以使用第一个坐标,例如:通过制作嵌套的辅助函数:
polygon :: [Coord] -> [Coord]
polygon [] = ...
polygon (pFirst:pRest) = ...
where
polygon' :: [Coord] -> [Coord]
polygon' (p1:p2:ps) = ...
polygon' [pLast] = ...
polygon' [] = ...
这是构造一个显式递归函数的一种方法。
如果您打算使用标准库,另一种方法可能是:
import Data.List (concat, zipWith, tail, cycle)
polygon :: [Coord] -> [Coord]
polygon [] = []
polygon ps = concat (zipWith line ps (tail (cycle ps)))