Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - sortBy function

Tags:

haskell

I have a list of vectors. But now I want to sort this list of vectors by their length, using the sortBy function. What I have already is:

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)])

The vectorLength function does work.

map vectorLength [(1,4), (2,6), (-2,-8),(3,-4)]   
output: [4.1231055, 6.3245554, 8.246211, 5.0]

I want when calling the following function

sortVectors [(1,4), (2,6), (-2,-8), (3,-4)]  
output: [(-2,-8), (2,6), (3,-4), (1,4)]

But I get the following error:

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

Thank you for your help. Here is my solution

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)])
like image 858
fibera Avatar asked May 11 '11 13:05

fibera


People also ask

How do you use sortBy in Haskell?

The sortBy function is the non-overloaded version of sort. >>> sortBy (\(a,_) (b,_) -> compare a b) [(2, "world"), (4, "!"), (1, "Hello")] [(1,"Hello"),(2,"world"),(4,"!")] sortBy sorts the specified Seq according to the specified comparator.

Is Haskell sort stable?

The sort is stable. If stability is not required, unstableSort can be slightly faster. A Haskell sorting toolkit A library of general-purpose sorting utilities.


2 Answers

You just write:

sortBy (comparing vectorLength) ....

You gave a list as first element to sortBy, but a function is required.

To write it out, what you want is:

sortBy comparVectors listofvectors
    where comparVectors a b = vectorLength a `compare` vectorLength b
like image 136
Ingo Avatar answered Oct 27 '22 00:10

Ingo


The Perl people call the following pattern the Schwartzian_transform

Just change your list into a list of key-value pairs and sort by key. (This avoids extra computations of the key function if it is expensive-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
like image 40
hugomg Avatar answered Oct 27 '22 00:10

hugomg