Min & Max without Bounded

Jon Purdy evincarofautumn at gmail.com
Tue Nov 10 22:57:21 UTC 2020

On Tue, Nov 10, 2020 at 1:33 PM Hécate <hecate at glitchbra.in> wrote:

> I invite you to read the source of this module, which may provide some
> context for the current situation:
> https://hackage.haskell.org/package/base-

Thanks! That is useful context. I was aware that this had been considered
as a possibility, but having coincidentally run into it multiple times
recently, I figured I’d propose it in earnest. Since there are two
reasonable ways to define these, I would prefer to have both available.
There’s an analogous situation, albeit not for the same reasons afaik, with
‘First’ and ‘Last’ from ‘Data.Semigroup’ (without ‘Maybe’) and
‘Data.Monoid’ (with ‘Maybe’). I wonder if that’s considered a good example
to follow (i.e. adding ‘Data.Monoid.{Max,Min}’) or more an unfortunate side
effect of how ‘semigroups’ was integrated into ‘base’.

On Tue, Nov 10, 2020 at 1:58 PM Oleg Grenrus <oleg.grenrus at iki.fi> wrote:

> Aren't Min and Max sufficient by themselves:
> >>> foldMap (Just . Min &&& Just . Max) [1..10 :: Integer]
> (Just (Min {getMin = 1}),Just (Max {getMax = 10}))

That’s a good point, and also a suitable alternative, thank you. I guess
the main question is whether anyone thinks it important enough to add a
separate type to provide different instances than this, for example ‘Ord’
as I mentioned. If not, I’m satisfied to use this or my own definitions.

(More likely the latter, if anyone’s curious, since I also have parallel
types for lower & upper bounds, where ‘Nothing’ is a zero rather than a

On Tue, Nov 10, 2020 at 1:19 PM Jon Purdy <evincarofautumn at gmail.com> wrote:

> 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
> confusion/bugs.
> 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/a5c07427/attachment.html>

More information about the Libraries mailing list