Reputation: 271
comp shows if two words are lexicographically equal or smaller
import Data.Char
class MyComp a where
comp :: a -> a -> Bool
instance MyComp Char where
comp num1 num2 = (ord num1) <= (ord num2) -- ord :: Char -> Int
instance MyComp a => MyComp [a] where
comp [] _ = True
comp _ [] = False
comp (x:xs) (y:ys)
| comp x y && comp y x = comp xs ys
| comp x y = True
| otherwise = False
The code above is little cryptic to me. Can someone explain to me what is going on in the guards? Why are they checking to see if both comp x y
and comp y x
are true. Shouldn't just
| comp x y = comp xs ys
| otherwise = False
do the trick?
Upvotes: 0
Views: 146
Reputation: 23548
comp
is basically an extended less-than-or-equals function.
The code you have a question about is about extending a definition of less-than-or-equal from type a
to type [a]
. It does this with the traditional definition of lexicographic ordering.
Now, as there is no formal relationship between MyComp
and Eq
you can't really ask x == y
- instead, the only way to ask if x
and y
are equal according to comp
is to do the double test you ask about there.
That double test is to handle this case:
"abcd" `comp` "aacd"
Now, this should be false because "aacd"
should sort before "abcd"
. But to do that you need to check beyond the first letter. That's what the code you're asking about is doing - it's checking the second (and subsequent) letters in the case where the initial letters are equal.
But you don't always check the subsequent letters! What about the case:
comp "abcd" "baaa"
Obviously, this should be true even though comp 'a' 'b'
is true and comp "bcd" "aaa"
is false.
Upvotes: 2
Reputation: 23870
It appears from the definition of MyComp
that the intention is that comp x y
is equivalent to x <= y
. Now, the definition instance MyComp a => MyComp [a]
means that if the less-than-or-equal-to relation is defined for values of type a
, then it is also defined for values of type [a]
, presumably using the lexicographical order.
The way the lexicographical order works is that if you are comparing two lists, you first compare the first element of the first list with the first element of the second list. If they differ, then you use the result of that comparison as the result of the comparison of the two lists. If on the other hand they are equal, then you look at the second element from both lists and so on. That's what the above code is trying to do: comp x y && comp y x
is like saying that x <= y && y <= x
, which is equivalent to saying that x
is equal to y
. If the happens. then according to the lexicographical order, you have to discard those two elements and look at the remainder of the two lists.
Upvotes: 1