Skip to content

Instantly share code, notes, and snippets.

@Pet3ris
Created August 11, 2012 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pet3ris/3325852 to your computer and use it in GitHub Desktop.
Save Pet3ris/3325852 to your computer and use it in GitHub Desktop.
Comparison chaining for a blog post
import Data.Monoid
chain :: (Ord a) => [a] -> [a] -> Ordering
chain xs = mconcat . (zipWith compare xs)
chain [1, 2, 3] [1, 2, -1]
-- GT
chain [1, 2, 3] [1, 2, 3]
-- EQ
chain [1, 2, 3] [1, 2, 4]
-- LT
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.aString, that.aString)
.compare(this.anInt, that.anInt)
.compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
.result();
}
public int compareTo(Foo that) {
int c1 = this.aString.compareTo(that.aString);
if (c1 != 0) return c1;
int c2 = this.anInt.compareTo(that.anInt);
if (c2 != 0) ...
}
-- lexicographical ordering
instance Monoid Ordering where
mempty = EQ
LT `mappend` _ = LT
EQ `mappend` y = y
GT `mappend` _ = GT
mconcat = foldr mappend mempty
import Control.Monad.Error
type Comparison = Either Ordering ()
unchain :: Ordering -> Comparison
unchain EQ = Right ()
unchain LT = Left LT
unchain GT = Left GT
runChain :: Comparison -> Ordering
runChain (Right _) = EQ
runChain (Left x) = x
-- Either requires an error instance, this is a bit ugly
instance Error Ordering where
noMsg = LT
strMsg _ = LT
-- Lowest possible precedence
infixl 0 <?
(<?) :: (Ord a) => a -> a -> Comparison
a <? b = unchain $ compare a b
runChain $ do
1 <? 1
"abc" <? "ab" ++ "c"
2.0000 <? 1.9999
-- GT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment