<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>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.<br>
      <br>
      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".<br>
    </p>
    <p>[1] <a class="moz-txt-link-freetext" href="https://hackage.haskell.org/package/lattices">https://hackage.haskell.org/package/lattices</a><br>
    </p>
    <div class="moz-cite-prefix">On 11.11.2020 0.57, Jon Purdy wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAE3FWBu-M5WXki75Eu_f6n8Gj6V7EYPt+r_0LEdLQuedrLEhCA@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div><br>
        </div>
        <div>On Tue, Nov 10, 2020 at 1:33 PM Hécate <<a
            href="mailto:hecate@glitchbra.in" moz-do-not-send="true">hecate@glitchbra.in</a>>
          wrote: <br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I
          invite you to read the source of this module, which may
          provide some context for the current situation:<br>
          <br>
          <a
href="https://hackage.haskell.org/package/base-4.14.0.0/docs/src/Data.Functor.Utils.html#%23"
            target="_blank" moz-do-not-send="true">https://hackage.haskell.org/package/base-4.14.0.0/docs/src/Data.Functor.Utils.html#%23</a></blockquote>
        <div><br>
        </div>
        <div>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’.<br>
        </div>
        <div><br>
        </div>
        <div>On Tue, Nov 10, 2020 at 1:58 PM Oleg Grenrus <<a
            href="mailto:oleg.grenrus@iki.fi" moz-do-not-send="true">oleg.grenrus@iki.fi</a>>
          wrote:</div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div>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}))<font
              color="#888888"><br>
            </font></div>
        </blockquote>
        <div><br>
        </div>
        <div>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.<br>
          <br>
          (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.)<br>
          <br>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, Nov 10, 2020 at 1:19
          PM Jon Purdy <<a href="mailto:evincarofautumn@gmail.com"
            moz-do-not-send="true">evincarofautumn@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <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>
        </blockquote>
      </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>