1

Good afternoon,

I'm a newb to Haskell, and I'm trying to adapt a QuickSort algorithm I made to sort lists of 'Int' with a list of tuples, but I quite can't figure out how to bind the tail to 'a' to make it work as I need it to, or if it's possible to reuse the code at all. Here's what I've been using to sort lists of 'Int':

quickSort :: Ord a => [a] -> [a]
quickSort [] = []  
quickSort (x:xs) =   
let smallSort  = quickSort [a | a <- xs, a < x]  
    biggerSort = quickSort [a | a <- xs, a > x]  
in  smallSort ++ [x] ++ biggerSort

And here is what I've tried to do with it so I could sort lists of tuples (Int,[Int]). I want to sort the tuples by the first element of the tuple, so if I get a lista like [(2,[1]),(1,[]),(3,[2,1])] it returns this [(1,[]),(2,[1]), (3,[2,1])].

quickSortTuplas ((x,(ks)) : []) = [(x,(ks))]
quickSortTuplas ((x,(ks)):ps) =   
let smallSort  = quickSort [a | a <- ps, a < x]  
    biggerSort = quickSort [a | a <- ps, a > x]  
in  smallSort ++ [(x,(ks))] ++ biggerSort

If I try to load this, I get the following error:

 Occurs check: cannot construct the infinite type: a ~ (a, [a1])
* In the second argument of `(>)', namely `x'
  In the expression: a > x
  In a stmt of a list comprehension: a > x
* Relevant bindings include
    a :: (a, [a1]) (bound at reNuevoHaskell.hs:60:37)
    biggerSort :: [(a, [a1])] (bound at reNuevoHaskell.hs:60:9)
    ps :: [(a, [a1])] (bound at reNuevoHaskell.hs:58:27)
    ks :: [a1] (bound at reNuevoHaskell.hs:58:22)
    x :: a (bound at reNuevoHaskell.hs:58:19)
    quickSortTuplas :: [(a, [a1])] -> [(a, [a1])]
      (bound at reNuevoHaskell.hs:57:1)

Many thanks in advance for any insight you could give me.

ViniV
  • 39
  • 5
  • I know that Quicksort should use "=" in one of the bindings, but I don't need to store duplicates. – ViniV May 19 '21 at 10:22
  • Thanks for the answer Ismor, the tuples I'm using are like [(1,[]),(2,[1]), (3,[2,1]),...]. I want to sort them by the first element, the Int on (Int, [Int]), without paying attention to the second element, but I get an error when I try to load the code above. – ViniV May 19 '21 at 11:12
  • 1
    Your `quickSort` implementation should work with `[(Int,[Int])]` since if implements `Ord` too – lsmor May 19 '21 at 11:13
  • 1
    And if the draw in the first element? what would be bigger `(0,[1,2])` of `(0,[0,1])` – lsmor May 19 '21 at 11:14
  • This function would be part of a bigger program, and a different function takes care of that type of situation(In wich both tuples (0,[1,2]), (0,[0,1]) would be merged into one tuple (0,[0,1,2]). It should never receive a tuple that's not already on the list, in wich case it would simply be dropped and not added, and if it does it's OK for the program to launch an exception, as it would mean the input wasn't properly written. – ViniV May 19 '21 at 11:19
  • I added the error I'm getting when I try to load the code to the post. Should have done it earlier, I'm sorry. – ViniV May 19 '21 at 11:20

1 Answers1

2

notice in the expresion [a | a <- ps, a < x] . a is a tuple whereas x is an Int. Hence a < x makes no sense. Any case, because your quicksort works on Ord a, you can use it for ordering a list of tuples as well. Try it`!

quickSort :: Ord a => [a] -> [a]
quickSort [] = []  
quickSort (x:xs) =   
  let smallSort  = quickSort [a | a <- xs, a < x]  
      biggerSort = quickSort [a | a <- xs, a > x]  
   in smallSort ++ [x] ++ biggerSort

main = print $ quickSort [(1,[2,3,4]) , (0, [4,5,6]), (2,[1,2,3])] -- This works fine
lsmor
  • 4,698
  • 17
  • 38
  • My goodness. I guess I still have a long way to go around type signatures. Many, many thanks my friend, you just took a massive headache away from me. – ViniV May 19 '21 at 11:30
  • 1
    And indeed you were absolutely right. The whole program now works as intended. Again, many thanks!! – ViniV May 19 '21 at 11:46