Min & Max without Bounded
Oleg Grenrus
oleg.grenrus at iki.fi
Wed Nov 11 08:37:13 UTC 2020
In lattices [1] package there is an Ordered newtype with a Lattice
instance where (/\) = min and (\/) = max. Then one can add extra
elements with Lifted (extra bottom), Dropped (extra top) or Levitated
(extra top and bottom). Finally one can convert a Lattice into Monoid
with Meet or Join newtypes.
This is to point out that there are various ways to think about this
issue. I don't think we have found /the/ solution to be in "base".
[1] https://hackage.haskell.org/package/lattices
On 11.11.2020 0.57, Jon Purdy wrote:
>
> On Tue, Nov 10, 2020 at 1:33 PM Hécate <hecate at glitchbra.in
> <mailto: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-4.14.0.0/docs/src/Data.Functor.Utils.html#%23
>
>
> 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
> <mailto: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 unit.)
>
>
> On Tue, Nov 10, 2020 at 1:19 PM Jon Purdy <evincarofautumn at gmail.com
> <mailto: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!
>
>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20201111/0a93b537/attachment-0001.html>
More information about the Libraries
mailing list