Sorting 在Haskell中对类型a使用排序时出错

Sorting 在Haskell中对类型a使用排序时出错,sorting,haskell,Sorting,Haskell,我是Haskell的新手,我正在尝试编写一个函数neights::Int->Metric a->Point a->[Point a]->[Point a],这样neights kd p xs根据点列表中的度量d到点p,按距离顺序返回k个最近邻的列表。我的代码是 type Point a = (a, a) type Metric a = Point a -> Point a -> Double type Tuple a = (Double, Point a) create:: Met

我是Haskell的新手,我正在尝试编写一个函数
neights::Int->Metric a->Point a->[Point a]->[Point a]
,这样
neights kd p xs
根据点列表中的度量d到点p,按距离顺序返回k个最近邻的列表。我的代码是

type Point a = (a, a)
type Metric a = Point a -> Point a -> Double
type Tuple a = (Double, Point a)

create:: Metric a -> Point a -> [Point a] ->  [Tuple a] -> [Tuple a]
create d p (x:xs) ys | length xs == 0 = sort(((d p x), x) : ys)
                     | otherwise      = create d p xs (((d p x), x) : ys)

takeP:: Tuple a -> Point a
takeP (_,p) = p   

pList::  [Tuple a] ->[Point a]-> [Point a]
pList (x:xs) ys | length xs == 0 = reverse (takeP x : ys)
                | otherwise      = pList xs (takeP x : ys) 

neighbours :: Int -> Metric a -> Point a -> [Point a] -> [Point a]--
neighbours k d p xs = take k (pList (create d p xs []) [])
但我在排序时遇到一个错误,即:

* No instance for (Ord a) arising from a use of `sort'
  Possible fix:
    add (Ord a) to the context of
      the type signature for:
        create :: forall a.
                  Metric a -> Point a -> [Point a] -> [Tuple a] -> [Tuple a]
* In the expression: sort (((d p x), x) : ys)
  In an equation for `create':
      create d p (x : xs) ys
        | length xs == 0 = sort (((d p x), x) : ys)
        | otherwise = create d p xs (((d p x), x) : ys)
起初我使用了
类型点a=(Int,Int)
,它工作正常,但在规范中要求该点是
类型点a=(a,a)
,这导致了我的错误。另一个问题是,我无法更改函数类型,因此不能按照建议添加
(Ord a)


有没有一种方法可以按第一个变量对元组列表进行排序而不会遇到错误?

create
函数中,可以使用:

create
函数使用了一些反模式,比如使用
length
,这需要线性时间。实际上,您可以将其重写为对映射进行排序:

create :: Ord a => Metric a -> Point a -> [Point a] -> [Tuple a]
create d p = sort . map f
    where f x = (d p x, x)

由于您在
((dpx),x):ys上
排序
,因此需要为
创建
,添加一个类型约束,因此
创建::Ord a=>度量a->点a->[点a]->[元组a]->[元组a]
。还要注意
长度xs
在这里不是一个好主意,因为它需要线性时间,您可以使用
null xs
代替。添加
Ord a=>
还需要将其添加到
neights
,这将更改所需的函数类型,即
neights::Int->Metric a->Point a->[Point a]->[Point a]
感谢您对
length xs
的说明,当然,类型约束是可传递的。如果您只想在
Double
上排序,您可以使用
sortOn fst
来代替。我在
create
函数上使用了您的建议,并在必要时添加了
Ord a=>
,而且似乎自动测试没有抱怨将
Ord a=>
添加到函数类型,并且测试通过了,所以我猜它工作得很好。谢谢你的快速回复。
create :: Ord a => Metric a -> Point a -> [Point a] ->  [Tuple a] -> [Tuple a]
create d p (x:xs) ys | length xs == 0 = sort(((d p x), x) : ys)
                     | otherwise      = create d p xs (((d p x), x) : ys)
create :: Ord a => Metric a -> Point a -> [Point a] -> [Tuple a]
create d p = sort . map f
    where f x = (d p x, x)
create :: Metric a -> Point a -> [Point a] -> [Tuple a]
create d p = sortOn fst . map f
    where f x = (d p x, x)