Функция Haskell - sortBy
У меня есть список векторов. Но теперь я хочу отсортировать этот список векторов по их длине, используя функцию sortBy. Что у меня уже есть:
import Data.List
vectorLength::(Int,Int)->Float
vectorLength(x,y) = sqrt(fromIntegral ((x^2)+(y^2)))
sortVectors::[(Int, Int)]->[(Int, Int)]
sortVectors list = sortBy(map vectorLength list) list
main = do
print(map vectorLength [(1,4), (2,6), (-2, -8), (3, -4)])
print(sortVectors[(1,4), (2,6), (-2,-8), (3, -4)])
Функция vectorLength работает.
map vectorLength [(1,4), (2,6), (-2,-8),(3,-4)]
output: [4.1231055, 6.3245554, 8.246211, 5.0]
Я хочу, чтобы вызвать следующую функцию
sortVectors [(1,4), (2,6), (-2,-8), (3,-4)]
output: [(-2,-8), (2,6), (3,-4), (1,4)]
Но я получаю следующую ошибку:
Couldn't match expected type `(Int, Int)' with actual type `[a0]'
Expected type: (Int, Int) -> (Int, Int) -> Ordering
Actual type: [a0] -> [b0]
In the return type of a call of `map'
In the first argument of `sortBy', namely `(map vectorLength list)'
In the expression: sortBy (map vectorLength list) list
Благодарим вас за помощь.
Вот мое решение
import Data.List
vectorLength::(Int,Int)->Float
vectorLength(x,y) = sqrt(fromIntegral ((x^2)+(y^2)))
sortVectors::[(Int, Int)]->[(Int, Int)]
sortVectors list = rever(sortBy compareVectors list)
rever::[(Int, Int)]->[(Int, Int)]
rever [] = []
rever (x:xs) = rever xs ++ [x]
compareVectors::(Int, Int) ->(Int, Int) ->Ordering
compareVectors(a,b) (c,d)
| vectorLength(a,b) < vectorLength(c,d) = LT
| vectorLength(a,b) > vectorLength(c,d) = GT
main = do
print(map vectorLength [(1,4), (2,6), (-2, -8), (3, -4)])
print(sortVectors[(1,4), (2,6), (-2,-8), (3, -4)])
Ответы
Ответ 1
Вы просто пишете:
sortBy (comparing vectorLength) ....
Вы указали список как первый элемент sortBy, но требуется функция.
Чтобы записать это, вы хотите:
sortBy comparVectors listofvectors
where comparVectors a b = vectorLength a `compare` vectorLength b
Ответ 2
Люди Perl называют следующий шаблон Schwartzian_transform
Просто измените свой список на список пар ключ-значение и выполните сортировку по ключу. (Это позволяет избежать дополнительных вычислений ключевой функции, если это дорогостоящий ish)
sortByKey keyf xs =
let k_xs = map (\x-> (keyf x, x)) xs in
let sorted = sortBy (compare `on` fst) k_xs in
map snd sorted
sortByKey vectorLength vectors