On Mon, 12 Dec 2005, Bulat Ziganshin wrote:

Hello

sometimes, Eq/Ord classes can't be derived automatically because we
need to comare only part of fields. in such situations i use the
following trick to easify generation of class instances:

data ArchiveBlock = ArchiveBlock {
                       blArchive     :: Archive
                     , blType        :: BlockType
                     , blCompressor  :: Compressor
                     , blPos         :: Integer
                     , blOrigSize    :: Integer
                     , blCompSize    :: Integer
                     , blCRC         :: CRC
                     , blFiles       :: Int
                   }

instance Eq ArchiveBlock where
 (==)    =  map2eq  $ map3 (blArchive,blPos,blCRC)

instance Ord ArchiveBlock where
 compare =  map2cmp $ map2 (blArchive,blPos)

{-
instance Ord ArchiveBlock where
 compare =  map2cmp blPos  -- for comparision on just one field
-}



I solved that problem with two generic functions:

Compare the same item of two records.

compareField :: Ord b => (a -> b) -> a -> a -> Ordering
compareField f x y = compare (f x) (f y)

Lexicographically compare a list of attributes of two records.

compareRecord :: [a -> a -> Ordering] -> a -> a -> Ordering
compareRecord cs x y =
   head (dropWhile (EQ==) (map (\c -> c x y) cs) ++ [EQ])

Use it this way:

instance Ord ArchiveBlock where
   compare =
      compareRecord
         [compareField blArchive,
          compareField blPos,
          compareField blCRC]
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to