Search code examples
sortinghaskellord

Missing first element from list output in Haskell


I am a beginner in Haskell and I am missing a concept while using Ord. I am trying to unique pairs out of a list in Haskell through the function below

pairs:: (Ord a) => [a] -> [(a,a)]
pairs[] = []
pairs(x:xs) = [(i, j) | i <- xs, j <- xs, i > j]

So for example if i want to get the unique pairs of [4,3,1,2] i should get the output [(4,3),(4,1),(4,2),(3,1),(3,2),(2,1)]

but I am getting [(3,1),(3,2)] instead.

my question is, why is this skipping the first element of the list xs?

Thanks.


Solution

  • My question is, why is this skipping the first element of the list xs?

    It is not skipping the first element of the list xs. It is just skipping x. (x:xs) is a pattern where x is the "head" of the list (the first item), whereas xs is the tail of the list (a list containing the remaining elements).

    You thus likely want to use:

    pairs:: (Ord a) => [a] -> [(a,a)]
    pairs xs = [(i, j) | i <- xs, j <- xs, i > j]

    Here we thus capture the entire list xs.

    If the order does not matter much, we can make this a bit more efficient by calculating the minimum and maximum, and iterating over the tails:

    import Data.List(tails)
    
    order2 :: Ord a => a -> a -> (a, a)
    order2 x y | x > y = (x, y)
               | otherwise = (y, x)
    
    pairs:: (Ord a) => [a] -> [(a,a)]
    pairs xs = [order2 i j | (i:js) <- tails xs, j <- js, i /= j]

    Here we thus first take an element i, and the remaining elements are stored in js. We then iterate over js. If i and j are not the same, we use order2 to create a 2-tuple where the first item is larger than the second item.