How to check if a string is smaller than in Haskell?

I have two lines specified as arguments to the Haskell function.

s1 less than s2 if s1 shorter than s2 or if they have the same length and s1 lexicographically less than s2 .

How to implement this in Haskell?

+6
string haskell compare
source share
6 answers

I would use something like the following:

 smaller :: String -> String -> Bool smaller s1 s2 | len1 /= len2 = (len1 < len2) | otherwise = (s1 < s2) where (len1, len2) = (length s1, length s2) 

Here's a sample run in Hugs:

  Main> smaller "b" "aa"
 True
 Main> smaller "aa" "b"
 False
 Main> smaller "this" "that"
 False
 Main> smaller "that" "this"
 True
+9
source share

Single pass solution:

 lengthcompare :: Ord a => [a] -> [a] -> Ordering lengthcompare = lc EQ where lc lx [] [] = lx lc _ [] _ = LT lc _ _ [] = GT lc EQ (v:vs) (w:ws) = lc (compare vw) vs ws lc lx (_:vs) (_:ws) = lc lx vs ws smaller :: Ord a => [a] -> [a] -> Bool smaller s1 s2 = lengthcompare s1 s2 == LT 
+7
source share

Try the following:

 compare s1 s2 

(This returns LT, EQ or GT).

+5
source share

A shorter version of the mappend version from Tom Lokhorst is higher:

 import Data.Monoid (mappend) import Data.Ord (comparing) compareStrings :: String -> String -> Ordering compareStrings = comparing length `mappend` comparing id 

Another way to take advantage of tuple ordering is:

 import Data.Ord (comparing) import Control.Arrow ((&&&)) compareStrings :: String -> String -> Ordering compareStrings = comparing (length &&& id) 
+4
source share

String is an instance of Ord , so you can use all of these methods to lexicographically compare a string. As Andrei said, this is essentially compare , but also comparison operators (<) .

 smaller :: Ord a => a -> a -> Bool smaller ab = a < b 

This works for all types implementing Ord (and is actually just a rough shell for (<) ), including String .

+2
source share

Normal string comparisons only work with lexicographic ordering, not with string lengths.

So, you will need to write your own function to also check the length:

 smaller :: String -> String -> Bool smaller s1 s2 | length s1 < length s2 = True | length s1 > length s2 = False | otherwise = s1 < s2 

Or a little more general:

 compareStrings :: String -> String -> Ordering compareStrings s1 s2 | length s1 < length s2 = LT | length s1 > length s2 = GT | otherwise = compare s1 s2 

Example:

 ghci> compare "ab" "z" LT ghci> compareStrings "ab" "z" GT 

We got together with Monoids at the university last week, and we came up with this great alternative example of Ord :

 instance Ord a => Ord [a] where compare = comparing length `mappend` comparing head `mappend` comparing tail 

But if you do not quite understand this, I suggest you stick to the first definition :-)

+2
source share

All Articles