[英]Lazy generation of pairs of adjacent elements in a “circular list”
为了检查光线三角形碰撞,我们可以首先看到光线是否与三角形的平面碰撞。 如果是,我们检查交叉点是否在所有三角形边的同一侧。 如果为true,则表示该点位于三角形内。 此过程类似于矩形和其他凸形图。
这是属于矩形的顶点列表(逆时针有序):
vertexes = [ll, lr, ur, ul]
我希望生成一个包含所有方面的列表; 也就是说,所有相邻的顶点对:
vertexPairs = [(ll, lr), (lr, ur), (ur, ul), (ul, ll)]
(注意最后一个顶点ul也与第一个顶点成对, ll )
我怎么能懒惰地生成一个通用凸几何图形的列表,假设我有一个有序的顶点列表?
我们的想法是将每个对提供给一个函数isInside ,并检查它的所有返回值是否相同。 这就是我正在做的事情:
1. vertexes = [<list of vertexes>]
2. vertexPairs = ???
3. results = map (\(v1, v2) -> isInside point v1 v2) vertexPairs
4. allequal = all (== head results) (tail results)
因为Haskell是惰性的,如果对isInside的调用返回的值与第一个调用的返回值不同,则对所有的调用结束(第4行)。 同样,我想要一种以懒惰方式生成vertexPairs列表的方法。
当我写这个问题时,我想到了生成对的可能解决方案 :
vertexPairs = zip (vertexes) (tail vertexes ++ [head vertexes])
尽管tikhon回答了大多数问题,但如果你想以更漂亮的方式写出来,你可以做到
vertexPairs v = zip v (tail $ cycle v)
这是有效的,因为当其中一个参数“耗尽”时, zip
停止生成列表
是的,这种生成列表的方式是懒惰的。 通常,Haskell中的列表函数是惰性的。
您可以通过在初始列表中包含会出错(例如undefined
)的内容来测试自己是否懒惰。 例如,如果
vertexes = [(0,0), (10,0), undefined, undefined]
然后vertexPairs
会给你一个错误(因为它需要评估整个列表来打印它)。 但是,如果它是懒惰的, head vertexPairs
应该仍然给你正确的对 - 它确实!
我认为你的代码实际上看起来相当不错。 tail vertexes ++ [head vertex]
使你正在做的事情非常清楚。 是的,在这里使用++
看起来有点奇怪,但这是有道理的:追加到列表的末尾是一项昂贵的操作,所以它应该脱颖而出。 我想不出有更好的方法来编写代码。 作为次要样式提示,您可以将括号放在vertexes
周围:
vertexPairs = zip vertexes (tail vertexes ++ [head vertexes])
对于3.,从概念上讲,您希望将isInside point
应用于每对。 现在它有一个像Point -> Point -> Bool
这样的类型。 你想得到一个函数,它将前两个参数作为元组:( (Point, Point) -> Bool
。 此函数称为uncurry
因为相反的转换(将一个将元组转换为多个参数之一的函数)称为currying。 所以你可以写3.像这样:
results = map (uncurry (isInside point)) vertexPairs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.