1

Can we put functions to determine the condition for our list comprehensions. Here is my code that I am trying to implement:

mQsort :: [String] -> [F.Record] -> [F.Record]
mQsort [] _ = []
mQsort c@(col:cond:cs) l@(x:xs) = (mQsort c small) ++ mid ++ (mQsort c large)
   where
    small = [y | y<-xs, (qGetStr col y) (qGetCond cond) (qGetStr col x)]
    mid   = mQsort cs [y | y<-l, (qGetStr col y) == (qGetStr col x)]
    large = [y | y<-xs, (qGetStr col y) (qGetCond' cond) (qGetStr col x)]

qGetStr :: String -> F.Record -> String
qGetStr col r | U.isClub col = F.club r
            | U.isMap col = F.mapName r
            | U.isTown col = F.nearestTown r
            | U.isTerrain col = F.terrain r
            | U.isGrade col =F.mapGrade r
            | U.isSW col = F.gridRefOfSWCorner r
            | U.isNE col = F.gridRefOfNECorner r
            | U.isCompleted col = F.expectedCompletionDate r
            | U.isSize col = F.sizeSqKm r
            | otherwise = ""

qGetCond "ascending" = (<)
qGetCond "decending" = (>)
qGetCond' "ascending" = (>)
qGetCond' "decending" = (<)

I get an error stating that the function qGetStr is applied to 4 arguments instead of 2.
Also, qGetCond - is this the right syntax to return an operator. I had to place the operator in brackets due to a compile error, but I have a feeling this is incorrect

1
  • 2
    You may be interested in sortBy. Commented Jan 10, 2012 at 18:59

1 Answer 1

8

Replace

small = [y | y<-xs, (qGetStr col y) (qGetCond cond) (qGetStr col x)]

with

small = [y | y<-xs, (qGetCond cond) (qGetStr col y) (qGetStr col x)]

Similarly for large.

The reason is the same as the reason for the syntax you use to return an operator in qGetCond. An operator is just a function really.

  • foo < bar is the same as (<) foo bar
  • foo `fire` bar is the same as fire foo bar

So you have to move the "operator" to the start of the expression in your list comprehension. (n.b. this is true in general and has nothing to do with list comprehensions in particular.)

Edit: to expand on Chris Kuklewicz's point:

  • Backticks only work around a single identifier. So foo `fire` bar is valid syntax, but something more complicated like foo `fire forcefully` bar or foo `(fire forcefully)` bar is a syntax error.

  • Parentheses round operators are more flexible. These expressions all evaluate to the same value:

    • foo < bar
    • (<) foo bar
    • (foo <) bar
    • (< bar) foo

    The last two forms are called operator sections. They are useful when passing a function to another function, e.g. map (+1) listOfIntegers. There are a couple of subtleties with the syntax:

    (quux foo <)      -- function calls are fine
    (baz + foo <)     -- syntax error because of the extra operator...
    ((baz + foo) <)   -- ...but this is ok
    (-3)              -- `-` is a special case: this is a numeric literal,
                      --                        not a function that subtracts three
    (subtract 3)      -- is a function that subtracts three
    
Sign up to request clarification or add additional context in comments.

1 Comment

If backticks worked on expressions instead of just symbols then (qGetStr col y) `(qGetCond cond)` (qGetStr col x) would have been valid. But backtick syntax sugar is not that general.

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.