<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Aren't Min and Max sufficient by themselves:<br>
      <br>
      >>> foldMap (Just . Min &&& Just . Max)
      [1..10 :: Integer]<br>
      (Just (Min {getMin = 1}),Just (Max {getMax = 10}))<br>
    </p>
    <p>- Oleg<br>
    </p>
    <div class="moz-cite-prefix">On 10.11.2020 23.19, Jon Purdy wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAE3FWBv7JSyj8LMG0C+dbXnrYzO_oWWBHyDjpYYRi79vSwYT7A@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div>
          <div>
            <div>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.<br>
              <br>
              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’:<br>
              <br>
            </div>
            newtype Minimum a = Minimum { getMinimum :: Maybe a }<br>
          </div>
          <div>  deriving (Eq, Ord, Monoid, Semigroup)<br>
          </div>
          <div>    via (Down (Maybe (Down (Max a))))<br>
          </div>
          <div><br>
          </div>
          newtype Maximum a = Maximum { getMaximum :: Maybe a }<br>
        </div>
        <div>  deriving (Eq, Ord, Monoid, Semigroup)<br>
        </div>
        <div>    via (Maybe (Max a))<br>
        </div>
        <div><br>
        </div>
        <div>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”.<br>
          <br>
        </div>
        <div>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.<br>
          <br>
        </div>
        <div>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.</div>
        <div><br>
        </div>
        <div>Any thoughts, critiques, questions, rebuttals, edge cases,
          use cases, &c. are most welcome!<br>
          <br>
        </div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
Libraries mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Libraries@haskell.org">Libraries@haskell.org</a>
<a class="moz-txt-link-freetext" href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a>
</pre>
    </blockquote>
  </body>
</html>