1

Trying to implement a function that will return a list of ints the represent an ordering of each list of doubles, e.g.:

orderings [ [1.0, 2.0, 3.0], [3.0, 2.0, 1.0] ]
> [ [0, 1, 2], [2, 1, 0] ]

However, having trouble with my pattern matching for some reason:

import Data.List

-- Return a list of orderings for each list of doubles
orderings:: [[Double]] -> [Int]
orderings [] = []
orderings x:xs = (ordering x):(orderings xs)

ordering:: [Double] -> [Int]
ordering xs = [i | (i, _) <- sorted] where
    sorted = sortBy (\(i1, e1) (i2,e2) -> compare e1 e2) $ zip [0..] xs

Error is:

Parse error in pattern: orderings

Can't see the error for the life of me!

3
  • See update, it's in the pattern of orderings Commented Feb 16, 2012 at 16:28
  • orderings = map ordering thanks! Commented Feb 16, 2012 at 17:48
  • 1
    Also, ordering = map fst . sortBy (compare `on` snd) . zip [0..]. on can be found in Data.Function; useful exactly for these situations. Commented Feb 16, 2012 at 18:06

4 Answers 4

5

Two more problems (in addition to the missing parentheses around x:xs):

  1. the type of orderings is wrong; I suspect it should be [[Double]] -> [[Int]]

  2. x is not in scope in ordering; I suspect it should be xs

Here's the corrected code:

import Data.List

-- Return a list of orderings for each list of doubles
orderings:: [[Double]] -> [[Int]]  -- changed type
orderings [] = []
orderings (x:xs) = (ordering x):(orderings xs)

ordering:: [Double] -> [Int]
ordering xs = [i | (i, _) <- sorted] where
    sorted = sortBy (\(i1, e1) (i2,e2) -> compare e1 e2) $ zip [0..] xs -- xs not x!
Sign up to request clarification or add additional context in comments.

1 Comment

Sorry - x was a typo - I got xs - Thanks! You are right on the signature however.
3

The result of orderings should be [[Int]] as pointed out previously. However, the implementation of the functions can be simplified to:

import Data.List

-- Return a list of orderings for each list of doubles
orderings :: [[Double]] -> [[Int]]
orderings = map ordering

ordering :: [Double] -> [Int]
ordering = map snd . sort . flip zip [0..]

3 Comments

Cool, that is great! But how do you know that sort will use the first item to sort on?
@drozzy: Tuples are ordered lexicographically by default, so as long as the first item in each tuple are distinct (as they are here), using the default ordering is the same as sorting by the first item.
@drozzy: What hammar said. That's why I flipped the zip, so that the Doubles would be first in the tuples.
2

You have to put parenthesis around the x:xs pattern:

orderings (x:xs) = ...

2 Comments

I remember that I was making this error 9 times out of 10 when beginning with haskell
Couldn't match expected type Int' with actual type [Int]' In the return type of a call of ordering' In the first argument of (:)', namely `(ordering x)' In the expression: (ordering x) : (orderings xs)
0

There are 3 errors:

In the line orderings x:xs = (ordering x):(orderings xs) you try to cons (:) a list and a list (but cons generates list with the given value prepended) and you forget the parens around the x:xs cons pattern match.

The type of : is:

Prelude> :type (:)
(:) :: a -> [a] -> [a]

The correct form of the line is:

orderings (x:xs) = (ordering x) ++ (orderings xs)

since ++ concats to lists:

Prelude> :type (++)
(++) :: [a] -> [a] -> [a]

The last error is that in the last line, it should be xs instead of x

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.