-1

How would I use the greater or less than sign as a variable so that when I enter Main> mySort (<) [1,5,3,6,4,1,3,3,2] or Main> mySort (>) [1,5,3,6,4,1,3,3,2] it will sort the list from highest to lowest or lowest to highest depending on which sign I chose to enter?

2 Answers2

4

You can just pass (<) in and use it compare each value.

A similar function

mySort :: (a -> a -> Ordering) -- Comparator function
       -> [a]
       -> [a]

And Haskell is so smart that this already exists as sortBy. This lets you pass in a function returning an Ordering which is just

data Ordering = LT | EQ | GT deriving(...)

But you have functions a -> a -> Bool so you need to make this into an ordering and then you can use it with sortBy.

wrap f a b | not $ f a b || f b a = EQ
           | f a b                = LT
           | otherwise            = GT

Now you can use this to wrap (<) and (>) to lift it to be used with sortBy

mySort :: (a -> a -> Bool) -> [a] -> [a]
mySort = sortBy . wrap
daniel gratzer
  • 52,833
  • 11
  • 94
  • 134
  • I think `wrap`'s guards would be nicer as `| f a b = LT`, `| f b a = GT` then `| otherwise = EQ`. – AndrewC Apr 24 '13 at 21:10
0

There already is a function in Data.List that does very similar thing to what you want, it is called sortBy.
However if you really want to implement it you could use sortBy like this:

mySort cop ls = sortBy (\a b -> if (cop a b) then LT else GT) ls

or even shorter (using eta reduction):

mySort cop = sortBy (\a b -> if (cop a b) then LT else GT)
Martinsos
  • 1,663
  • 15
  • 31
  • 1
    This is defeats the entire point of having higher order functions... – daniel gratzer Apr 24 '13 at 02:07
  • @jozefg Could you explain please? You are talking about passing function as an argument? Question I was answering was asking only for < and > so I didn't think it is needed to make it work for all kinds of functions. If question was to create a sort that accepts comparison function as an operator, then I agree this would not be a good idea. – Martinsos Apr 24 '13 at 02:11
  • 6
    Higher order functions let you do this sort of thing generically, what sortBy actually does is take a **function** and use that to produce the ordering, it's type sig is `sortBy :: (a -> a -> Ordering) -> [a] -> [a]` This is much lighter weight and more typesafe, using your method you could pass in ` '*' ` or something into your function and get a runtime error with no idea where it came from – daniel gratzer Apr 24 '13 at 02:12
  • @jozefg You are right, I also missused sortBy. I think it should be ok now – Martinsos Apr 24 '13 at 02:18