I encountered exactly this issue in my use of the Max & Min monoids in Reactive.  I wanted to allow already-bounded types to use their own minBound for Max and maxBound for Min, and also allow unbounded types to be used.  So, rather than entangling bound addition with Max & Min, I defined AddBounds type wrapper, which is *orthogonal* to Max & Min.  If your type is already Bounded, then use my simple Max & Min wrappers directly.  If not (as in Reactive's use), compose Max or Min with AddBounds.

I'm sorry I didn't think to mention this useful composition the Max & Min trac ticket.

   - Conal

On Thu, Sep 23, 2010 at 10:47 AM, Gregory Collins <greg@gregorycollins.net> wrote:
Felipe Lessa <felipe.lessa@gmail.com> writes:
> On Thu, Sep 23, 2010 at 12:58 PM, Jake McArthur <jake.mcarthur@gmail.com> wrote:
>
>>>    -- | Ordered monoid under 'max'.
>>>    newtype Max a = Max { getMax :: a }
>>>            deriving (Eq, Ord, Read, Show, Bounded)
>>>
>>>    instance (Ord a, Bounded a) => Monoid (Max a) where
>>>            mempty = Max minBound
>>>            Max a `mappend` Max b = Max (a `max` b)
>
> Why should we prefer this monoid over
>
>> data Max a = Minimum | Max a
>>              deriving (Eq, Ord, Read, Show)
>>
>> instance Ord a => Monoid (Max a) where
>>   mempty = Minimum
>>   Minimum `mappend` x   = x
>>   x `mappend` Minimum   = x
>>   Max a `mappend` Max b = Max (a `max` b)

You're right, the original wouldn't fly because there are unbounded
types (like Integer) that you'd like to be able to use with Max/Min.

Rather than your proposal I would suggest that Max/Min mirror
the existing First/Last, namely:

   newtype Max a = Max { getMax :: Maybe a }
     deriving (Eq, Ord, Read, Show)

   instance (Ord a) => Monoid (Max a) where
       mempty  = Max Nothing
       mappend = max

G
--
Gregory Collins <greg@gregorycollins.net>
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries