0

I have the following three functions. The function "distance" calculates the distance between two points. The function "calculatesDistances" takes a point (x1, y1) and a list of points [(x2, y2)] and uses the "distance" function to calculate the distance between (x1, y1) and every (x2, y2) in the list [(x2, y2)]. It returns a sorted list of points depending on their distance to (x1, y1). The function "closestDistances" returns the n closest points to (x1, y1) and it uses the sorted list from the function "calculatesDistances".

I think my algorithm is correct but as you can see my code for "calculatesDistances" is missing because I have no idea how to write this in Haskell. I am a beginner and I'm really struggling with Haskell syntax. Any help will be appreciated.

distance :: (Floating a, Ord a) => (a,a) -> (a,a)-> a
    distance (x1 , y1) (x2 , y2) = sqrt (x'*x' + y'*y')
        where
          x' = x1 - x2
          y' = y1 - y2

    Example outputs:
    *Main> distance (0,0) (1,0)
    1.0
    *Main> distance (0,0) (2,0)
    2.0
    *Main> distance (0,0) (3,0)
    3.0


    calculatesDistances :: (Floating a, Ord a) => (a,a) -> [(a,a)] -> [(a,a)]
    Psesudocode:
    Apply function distance to (x1 , y1) and every (x2 , y2) in [(x2 , y2)] and get a distance for every input
    Return the list [(x2 , y2)] but sorted in ascending order depending on the distance

    Expected output:
    *Main> calculatesDistances (0,0) [(3,0), (2,0),(-3,0), (1,0)]
     [(1,0),(2,0),(3,0),(-3,0)]


    closestDistances :: (Floating a, Ord a) => Int -> (a,a) -> [(a,a)] -> [(a,a)]
    closestDistances n (x1, y1) [(x2, y2)] = take n (calculatesDistances (x1, y1) [(x2, y2)])

    Expected output:

    *Main> closestDistances 3 (0,0) [(1,0),(2,0),(3,0),(-3,0)]
     [(1,0),(2,0),(3,0)]

    *Main> closestDistances 2 (0,0) [(1,0),(2,0),(3,0),(-3,0)]
     [(1,0),(2,0)]
4
  • haskell.org/hoogle/?q=sort Commented Nov 14, 2017 at 17:44
  • I know about this function but the sorting of the list depends on the outputs of the function "distance" for every two points. So how can I use it in this case? Commented Nov 14, 2017 at 17:50
  • 1
    haskell.org/hoogle/?q=sortBy Commented Nov 14, 2017 at 18:30
  • 1
    sortBy (comparing distance) list Commented Nov 14, 2017 at 18:43

1 Answer 1

2

You can use sortOn, which has type

sortOn :: Ord b => (a -> b) -> [a] -> [a]

and which sorts the as by comparing the output of the a -> b function. For example,

Data.List> sortOn (distance (0,0)) [(3,0), (1,1), (0,1)]
[(0.0,1.0),(1.0,1.0),(3.0,0.0)]

You might also consider writing a squaredDistance function which omits the sqrt for efficiency, since sqrt is monotonic and hence does not affect sort order.

Sign up to request clarification or add additional context in comments.

3 Comments

I got this error: <interactive>:92:1: error: Variable not in scope: sortOn :: ((Double, Double) -> Double) -> [(Integer, Integer)] -> t
@user408340 Did you import Data.List? What version of base do you have (you can ask with ghc-pkg list base)?
No, I forgot to import it. Thank you very much!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.