我正在编写一个程序,根据点列表ps中点p的度量d,按距离顺序返回k个最近邻居的列表。如果列表中的ps少于k个元素,则所有元素都应作为适当的邻居返回。此外,应该根据它们在列表ps中的初始顺序返回两个与p同样接近的点
import Data.List
type Point a = (a,a)
type Metric a = (Point a) -> (Point a) -> Double
nearPoints :: Int -> Metric a -> Point a -> [Point a] -> [Point a]
nearPoints k d p [] = []
nearPoints k d p ps = take k (sortOn (pointsDistCalc p) ps)
pointsDistCalc :: Metric Double
pointsDistCalc (t1,t1) (t2,t2) = sqrt(((t1-t2)^2)+((t1-t2)^2))
这是错误消息
* Couldn't match type `a' with `Double'
`a' is a rigid type variable bound by
the type signature for:
nearPoints :: forall a.
Int -> Metric a -> Point a -> [Point a] -> [Point a]
Expected type: Point Double
Actual type: Point a
* In the first argument of `pointsDistCalc', namely `p'
In the first argument of `sortOn', namely `(pointsDistCalc p)'
In the second argument of `take', namely
`(sortOn (pointsDistCalc p) ps)'
* Relevant bindings include
ps :: [Point a]
p :: Point a
d :: Metric a
nearPoints :: Int -> Metric a -> Point a -> [Point a] -> [Point a]
11 | nearPoints k d p ps = take k (sortOn (pointsDistCalc p) ps)
有人能帮我拿这个吗
您将pointsDistCalc
定义为Point Double
s的Metric
,因此这意味着按该距离排序的nearPoints
也应该是Point Double
s。
也就是说,签名表明给定了一个度量,因此而不是本身使用PointsDistCalc
。因此,您可以使用来实现此功能
nearPoints :: Int -> Metric a -> Point a -> [Point a] -> [Point a]
nearPoints _ _ _ [] = []
nearPoints kdp0 ps = take k (sortOn (dp0) ps)
这里没有必要将定义分为两种情况:如果给sortOn
一个空列表,它将返回一个空的列表:
nearPoints :: Int -> Metric a -> Point a -> [Point a] -> [Point a]
nearPoints kdp0 ps = take k (sortOn (dp0) ps)