Felix Schroeter wrote:
> > for instance, i could want to sort a list,
> > according to two different criteria,
> > using two different instances of Ord.
> 
> newtype IntFunnilyOrdered = IFO Int
> instance Ord IntFunnilyOrdered where
>   compare (IFO x) (IFO y) | even x && even y = compare x y
>                           | even x && odd y  = LT
>                           | odd x && even y  = GT
>                           | otherwise        = compare x y
> int_from_ifo (IFO x) = x
> 
> newtype IntReverse = IR Int
> instance Ord IntReverse where
>   compare (IR x) (IR y) = compare y x
> int_from_ir (IR x) = x
> 
> Now, you can do
>   map int_from_ir $ sort $ map IR l
> or
>   map int_from_ifo $ sort $ map IFO l

Trust me, if you have more than just a few ways to order, this method
gets real complicated real fast. You have to keep track of which list is
based on which 'newtype' and then constantly convert the newtype
back-and-forth to/from the original type when you add or retrieve an
element. The 'map' trick is a nifty work-around for this particular
instance, but it doesn't work well in general for "Bag" ADTs. That is
because the resulting list has lost all of its sorting information. In
order to insert a new element, the list would have to be converted back
into the newtype, insert the element, then convert list back to original
type. I'll be honest and admit that I haven't thought real hard about
how much the efficency will be affected by constantly mapping
back-and-forth with lazy evaluation, but my gut feel is that the
overhead of such a scheme will be expensive for any large Bag.


Reply via email to