{- | Copyright : (c) Henning Thielemann 2007 Maintainer : numericprelude@henning-thielemann.de Stability : provisional Portability : portable An alternative type class for Ord which allows an ordering for dictionaries like "Data.Map" and "Data.Set" independently from the ordering with respect to a magnitude. -} module Algebra.Indexable ( C(compare), ordCompare, liftCompare, ToOrd, toOrd, fromOrd, ) where import Prelude hiding (compare) import qualified Prelude as P {- | Definition of an alternative ordering of objects independent from a notion of magnitude. For an application see "MathObj.PartialFraction". -} class Eq a => C a where compare :: a -> a -> Ordering {- | If the type has already an 'Ord' instance it is certainly the most easiest to define 'Algebra.Indexable.compare' to be equal to @Ord@'s 'compare'. -} ordCompare :: Ord a => a -> a -> Ordering ordCompare = P.compare {- | Lift 'compare' implementation from a wrapped object. -} liftCompare :: C b => (a -> b) -> a -> a -> Ordering liftCompare f x y = compare (f x) (f y) instance (C a, C b) => C (a,b) where compare (x0,x1) (y0,y1) = let res = compare x0 y0 in case res of EQ -> compare x1 y1 _ -> res instance C a => C [a] where compare [] [] = EQ compare [] _ = LT compare _ [] = GT compare (x:xs) (y:ys) = compare (x,xs) (y,ys) instance C Integer where compare = ordCompare {- | Wrap an indexable object such that it can be used in "Data.Map" and "Data.Set". -} newtype ToOrd a = ToOrd {fromOrd :: a} deriving (Eq, Show) toOrd :: a -> ToOrd a toOrd = ToOrd instance C a => Ord (ToOrd a) where compare (ToOrd x) (ToOrd y) = compare x y