Firstly, using Text or ByteString instead of String can help without changing anything.
In general, I would not recommend creating an Eq instance that is not compatible with Ord . Libraries can rightfully rely on this, and you never know what strange problems it can cause. (For example, are you sure Map doesn't use the relationship between Eq and Ord ?)
If you don’t need an Eq instance at all, you can simply define
instance Eq BigThing where x == y = compare xy == EQ
Then equality will match. There is no requirement that equal values must have all fields equal.
If you need an Eq instance that compares all fields, you can stay consistent by wrapping BigThing in newtype , define Eq and Ord above it and use it in your algorithm when you need to sort by name :
newtype BigThing' abc = BigThing' (BigThing abc) instance Eq BigThing' where x == y = compare xy == EQ instance Ord BigThing' where compare (BigThing b) (BigThing b') = compare (name b) (name b')
Update:. Since you say that any order is acceptable, you can use hashing to your advantage. You can use the hashable package for this . The idea is that you pre-compute the hash values when creating the data and use them when comparing the values. If the two values are different from each other, he is almost sure that their hashes will be different, and you only compare their hashes (two integers), nothing more. It might look like this:
module BigThing ( BigThing() , bigThing , btHash, btName, btSurname ) where import Data.Hashable data BigThing = BigThing { btHash :: Int, btName :: String, btSurname :: String } -- etc deriving (Eq, Ord) -- Since the derived Eq/Ord instances compare fields lexicographically and -- btHash is the first, they'll compare the hash first and continue with the -- other fields only if the hashes are equal. -- See http://www.haskell.org/onlinereport/derived.html
Note that with this solution, the ordering will appear random without a visible relation to the fields.
You can also combine this solution with the previous ones. Or you can create a small module for packaging any type with its pre-computed hash (wrapped values should have Eq instances corresponding to their Hashable instances).
module HashOrd ( Hashed() , getHashed , hashedHash ) where import Data.Hashable data Hashed a = Hashed { hashedHash :: Int, getHashed :: a } deriving (Ord, Eq, Show, Read, Bounded) hashed :: (Hashable a) => a -> Hashed a hashed x = Hashed (hash x) x instance Hashable a => Hashable (Hashed a) where hashWithSalt salt (Hashed _ x) = hashWithSalt salt x