I was trying to avoid offering up color swatches for the bikeshed, but here are my thoughts:

The use-cases that most often arise are that you either want to:

1.) take the Min or Max of a common Bounded type. These have a nice analogues in Sum and Product in Data.Monoid now.

2.) take the Min or Max of an unbounded Type, and therefore need to have a unit added. These have nice analogues in First and Last in the Data.Monoid now, and reflect the practice of using the equivalent of Maybe to transform something that is notionally a Semigroup into a Monoid. This is common for things like priority queues. In fact, using a fingertree as a fair priority queue is really easy with this monoid. In Data.Monoid.Ord from the monoids package these are "MinPriority" and "MaxPriority" for that reason. Note that by adding just a minimum or maximum element these aren't strong enough to be Bounded, and this is the minimum requirement to really be able to implement a priority queue with any Ord'ered value as the priority, while handling the empty queue case gracefully.

On the other hand, composing AddBounds introduces another element on the other side, which serves as an annihilator when composed with Min and Max. This is fine for some applications, but I don't believe it subsumes MinPriority and MaxPriority.

AddBounds is a useful type, but I don't think injecting MinPriority a/MaxPriority a into the larger Max (AddBounds a) and Min (AddBounds a) is the right solution.

By that same 'the type is too large' token, I don't like just providing MinPriority/MaxPriority, since Min and Max are perfectly usable and much more efficient monoids with a smaller domain.

So in my perfect world the patch would include Min/Max/MinPriority/MaxPriority and another proposal could find a nice place to shoehorn AddBounds. ;)

-Edward Kmett

On Thu, Sep 23, 2010 at 2:25 PM, Conal Elliott <conal@conal.net> wrote:
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


_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://www.haskell.org/mailman/listinfo/libraries