问题代码如下。
type Point = (Float, Float)
xs = []
arrange_in_pairs :: Point -> Point -> [Point] -> [(Point, Point)]
arrange_in_pairs (x, y) (xi, yi) points
| length xs == 0 = xs ++ [((x, y), (points !! 0))]
| (length xs - 1) /= length points = xs ++ [((points !! (length xs - 1)), (points !! length xs))] arrange_in_pairs (x, y) (xi, yi) points
| otherwise = xs ++ [((points !! length xs), (xi, yi))] xs
这个想法是一个点是一个坐标,就像在图形上一样。 (x,y)是起点,(xi,yi)是终点,“ points”是它们之间的点的列表。该函数应该将每对点作为一个元组并将它们存储在列表中。因此,第一个元组是(x,y),“点”中的第一个点。第二个元组是“点”中的第一个点,第二个点是“点”中的第二点,依此类推,直到列表中的最后一个元组是“点”和(xi,yi)中的最后一个点。任何帮助都非常感谢。
我得到的错误是:
*** Expression : [(points !! (length xs - 1),points !! length xs)] arrange_in_pairs (x,y) (xi,yi) points
*** Term : [(points !! (length xs - 1),points !! length xs)]
*** Type : [((Float,Float),(Float,Float))]
*** Does not match : a -> b -> c -> d -> e
答案 0 :(得分:2)
您收到的错误是由于以下原因:
[((points !! (length xs - 1)), (points !! length xs))] arrange_in_pairs (x, y) (xi, yi) points
在Haskell中的事物之间放置空格时,表示正在调用函数。在这种情况下,该行的第一部分:
[((points !! (length xs - 1)), (points !! length xs))]
被解释为一个函数,被四个参数调用:
arrange_in_pairs
(x, y)
(xi, yi)
points
这就是为什么说Does not match : a -> b -> c -> d -> e
的原因。期望有一个带有四个参数并返回一个值的函数,但是它将看到类型为[((Float,Float),(Float,Float))]
的值。
我认为您在这里尝试使用xs ++ [...]
更新xs
的值,然后返回值arrange_in_pairs (x, y) (xi, yi) points
,也许吗?这有很多问题:
++
运算符不更新值,它只是连接两个列表并返回结果。 xs
不会更改。xs = []
,则除[]
之外,它将没有任何其他值。您需要使用其他方法,例如递归。@JorgeAdriano提到了一个更简洁的解决方案,但我认为它对理解原理没有太大帮助。如果要解决此问题,我的方法是尝试递归函数。为此,您需要做两件事:
points
为空,我们将返回什么?points
的第一个元素来决定结果的第一个元素应该是什么,我们还可以使用不同的参数再次调用该函数,以便为我们提供其余的输出。列表上的递归函数取决于cons(:
)构造函数。之所以提出这一点,是因为我注意到您没有在代码中使用它,但这很重要:
x:xs
返回一个列表,其中第一个元素为x
,其余元素为列表xs
中的元素。x:xs
将列表参数的第一个元素绑定到x
,并将其余元素绑定到列表xs
。如果列表为空,则x:xs
不匹配。[]
用作参数(在模式匹配中)时,仅在列表为空时匹配。基本情况(points
为空)是返回从起点到终点的单个线段。可以这样写:
arrange_in_pairs start end [] = [(start, end)]
递归情况更为复杂。我们知道第一个元素必须是从points
的起点到第一个元素的一段,因此我们可以从以下开始:
arrange_in_pairs start end (x:xs) = (start, x) : ???
我们不是将第三个参数绑定到points
,而是将它的第一个元素绑定到x
,其余的元素绑定到列表xs
。返回值是第一个元素(从start
到x
的一段),返回到其余元素(我们尚未定义的列表)。
到目前为止,太好了。 ???
应该是对arrange_in_pairs
的递归调用,并且应该以这样的方式进行调用:返回的第一个段是我们需要的下一个段。我们需要的下一个段是从x
到xs
的第一个元素,因此我们需要通过x
代替start
和xs
来代替points
:
arrange_in_pairs start end (x:xs) = (start, x) : arrange_in_pairs x end xs
完整功能如下:
arrange_in_pairs :: Point -> Point -> [Point] -> [(Point, Point)]
arrange_in_pairs start end [] = [(start, end)]
arrange_in_pairs start end (x:xs) = (start, x) : arrange_in_pairs x end xs
答案 1 :(得分:1)
提示:
所以第一个元组是(x,y),第一个点在“ points”中。第二个元组是“ points”中的第一个点,第二个点是“ points”中的第二个点,依此类推,直到列表中的最后一个元组是“ points”和(xi,yi)中的最后一个点。
有一个类型为{p>的函数zip
zip :: [a] -> [b] -> [(a, b)]
按位置将两个列表的元素配对。您还可以建立列表
list1 = [(x, y)] ++ points
list2 = points ++ [(xi,yi)]
一旦有了,就真的很近了。