Min & Max without Bounded

Jon Purdy evincarofautumn at gmail.com
Tue Nov 10 21:19:20 UTC 2020

The ‘Min’ and ‘Max’ newtypes from ‘Data.Semigroup’ require a ‘Bounded’
constraint for their ‘Monoid’ instances, because they wrap a value of type
‘a’ rather than ‘Maybe a’. The latter is something I’ve needed a few times
lately for types that cannot be bounded (or just don’t want to be), and it
seems base-worthy to me.

So if it hasn’t been proposed and dismissed already (or if it has been
proposed, but just got backburnered), I’d like to suggest adding the
following new types, and at least the following instances, to either
‘Data.Semigroup’ or ‘Data.Monoid’:

newtype Minimum a = Minimum { getMinimum :: Maybe a }
  deriving (Eq, Ord, Monoid, Semigroup)
    via (Down (Maybe (Down (Max a))))

newtype Maximum a = Maximum { getMaximum :: Maybe a }
  deriving (Eq, Ord, Monoid, Semigroup)
    via (Maybe (Max a))

These instances could be specified explicitly instead of with
‘DerivingVia’, but the essential notion here is that ‘Maximum’ uses its
empty value ‘Nothing’ as a “negative infinity”, less than all other ‘Just’
values, while ‘Minimum’ reverses that to use ‘Nothing’ as the corresponding
“positive infinity”.

I assume these would also want more or less the same array of instances as
for the existing ‘Min’ and ‘Max’, and there is the usual opportunity to
bikeshed about the naming and how these instances ought to relate to one
another. I figure that at least the ‘Ord’ instance should match the
ordering that the ‘Semigroup’ instance uses, to avoid some potential for

As for use cases, I tend to reach for these things either in configuration
records with many fields that I’m combining by semigroup append (Max, Any,
set union, and so on) or when I have a possibly-empty container and don’t
want to write e.g. ‘maximum (0 : xs)’ to avoid partiality. For example,
‘foldMap (Minimum . Just &&& Maximum . Just)’ computes the minimum and
maximum in a single pass, returning Nothing for a null input.

Any thoughts, critiques, questions, rebuttals, edge cases, use cases, &c.
are most welcome!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20201110/709a080e/attachment.html>

More information about the Libraries mailing list