I am writing a Haskell code to find a list of the k nearest neighbours, in distance order, according to metric d to point p in the list xs of points. My code is below
import Data.List
import Data.Function
type Point a = (a,a)
type Metric a = (Point a) -> (Point a) -> Double
neighbours :: Int -> Metric a -> Point a -> [Point a] -> [Point a]
neighbours k calDistance p [] = []
neighbours k calDistance p ps
| k < 0 = error "k cannot be negative"
| otherwise = take k (neighbours' (sortBy (compare `on` snd) [ (poi,dis) | (poi,dis) <- points p ps]))
neighbours' :: [(Point a, Double)] -> [Point a]
neighbours' xs = [ x | (x,y)<-xs]
points :: Point a -> [Point a] -> [(Point a, Double)]
points _ [] = []
points p1 (p2:px) = (p2,(calDistance p1 p2)): points p1 px
calDistance :: Metric Double
calDistance (x1,y1) (x2,y2) = sqrt((x1-x2)**2 + (y1-y2)**2)
The error is
• Couldn't match type ‘a’ with ‘Double’
‘a’ is a rigid type variable bound by
the type signature for:
points :: forall a. Point a -> [Point a] -> [(Point a, Double)]
at A4.hs:27:1-53
Expected type: Point Double
Actual type: Point a
• In the first argument of ‘calDistance’, namely ‘p1’
In the expression: (calDistance p1 p2)
In the first argument of ‘(:)’, namely ‘(p2, (calDistance p1 p2))’
• Relevant bindings include
px :: [Point a] (bound at A4.hs:29:15)
p2 :: Point a (bound at A4.hs:29:12)
p1 :: Point a (bound at A4.hs:29:8)
points :: Point a -> [Point a] -> [(Point a, Double)]
(bound at A4.hs:28:1)
|
29 | points p1 (p2:px) = (p2,(calDistance p1 p2)): points p1 px
|
However, if I change 'Metric Double' to 'Double a' there is also a compile error: Couldn't match expected type ‘Double’ with actual type ‘a’. Please can someone tell me how to solve it?