【发布时间】:2020-11-18 11:34:44
【问题描述】:
我对 Haskell 很陌生,我正在尝试编写一个函数 neighbours :: Int -> Metric a -> Point a -> [Point a] -> [Point a] 以便 neighbours k d p xs 返回 k 个最近邻居的列表,按照距离顺序,根据度量 d 到列表 xs 中的点 p点。我的代码是
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)
我一开始使用type Point a = (Int, Int),它工作正常,但在规范中要求Point 是type Point a = (a, a),这导致了我的错误。另一个问题是我不能更改函数类型,所以我不能按照建议添加(Ord a)。
有没有办法按第一个变量对元组列表进行排序而不会遇到错误?
【问题讨论】:
-
既然你
sort在((d p x), x) : ys上,你需要给create加上类型约束,所以create:: Ord a => Metric a -> Point a -> [Point a] -> [Tuple a] -> [Tuple a]。 -
还要注意
length xs在这里不是一个好主意,因为它需要线性时间,您可以改用null xs。 -
添加
Ord a =>需要将其也添加到neighbours,这将更改所需的函数类型,即neighbours :: Int -> Metric a -> Point a -> [Point a] -> [Point a] -
感谢
length xs的留言 -
是的,当然类型约束是可传递的。如果只想对
Double进行排序,可以改用sortOn fst。