<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">mathematical equivalences</blockquote><div><br></div><div>Yeah... Unfortunately, type classes aren't good at those. They're good for necessary conditions, and you can make them work for necessary and sufficient conditions, but only if you control the class in question. One major problem in your attempt is that you're not defining Bounded yourself, so you can't define necessary conditions (since those would have to be part of the class). If you controlled Bounded, you could do this:</div><div><br></div><div><font face="monospace,monospace">class UpperBounded a where ...</font></div><div><font face="monospace,monospace">class LowerBounded a where ...</font></div><div><font face="monospace,monospace">class (UpperBounded a, LowerBounded a) => Bounded a -- This is the "necessary" part; notice no "..."</font></div><div><font face="monospace,monospace">instance (UpperBounded a, LowerBounded a) => Bounded a -- This is the "sufficient" part</font></div><div><font face="monospace,monospace"><br></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">You'd need to turn on some extensions (UndecidableInstances and FlexibleContexts, IIRC).</font></font><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 8, 2018 at 6:24 PM, Graham Gill <span dir="ltr"><<a href="mailto:math.simplex@gmail.com" target="_blank">math.simplex@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Thanks for the explanation David. The problem is clear from your description, and when you *really* do want to do it anyway I guess that's what the INCOHERENT and OVERLAPS/OVERLAPPING pragmas are for, to help you control the types.</span><span class=""><br><div><span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Just remember that they are "typeclasses", not "classclasses".</span></span></blockquote><div><br></div></span><div>Actually I wasn't thinking in terms of "classclasses", instead, of mathematical equivalences. A set of reals is bounded iff it is both upper and lower bounded. I wanted to try to express that in types, and wondered if I could do it without resorting to asymmetrical syntax (the newtype suggestion).</div><div><br></div><div>Regards,</div><div>Graham</div><div><br></div></div><div class="HOEnZb"><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 4, 2018 at 8:54 AM David McBride <<a href="mailto:toad3k@gmail.com" target="_blank">toad3k@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>This is a common thing that people try to do.  I want class A to apply to any type in which class B already applies.  It seems to mimic what would work in object oriented programming and it is hard to see at first why it doesn't work in haskell.</div><div><br></div><div>Just remember that they are "typeclasses", not "classclasses".  When you write</div><div><br></div><div>class Foo a where foo :: ...<br></div><div>instance Show a => Foo a where foo = something<br></div><div><br></div><div>Everything seems fine, but then you could write additional classes like this</div><div><br></div><div>instance Read a => Foo a where foo = something_else<br></div><div><br></div><div>And what if you had a type that is both a Read and Show, like Int?  Now there are two different things it could do -- something and something_else.  How to decide?  Based on order?  But then the behavior of the program could dramatically change based on the import order.<br></div><div><br></div><div>I would advise you to treat Bounded, UpperBounded, and LowerBounded to be separate properties and define them on all types explicitly rather than trying to obtain instances for free.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jun 3, 2018 at 11:42 PM, Graham Gill <span dir="ltr"><<a href="mailto:math.simplex@gmail.com" target="_blank">math.simplex@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Please see the paste: <a href="https://pastebin.com/zBim7Zkx" target="_blank">https://pastebin.com/<wbr>zBim7Zkx</a></div><div><br></div>I'm experimenting with defining UpperBounded and LowerBounded typeclasses. An example type belonging to the latter that is not also Bounded would be type Natural from Numeric.Natural.<div><br></div><div>I want to say that if a type is Bounded, then it is also UpperBounded and LowerBounded. If a type is both UpperBounded and LowerBounded, then it is also Bounded.</div><div><br></div><div>To express the constraints, I need FlexibleInstances and UndecidableInstances extensions. These allow the module to load into ghci (8.4.2) with only a warning, but, without the INCOHERENT pragmas, I get an overlapping instance error if I try to evaluate minBound, maxBound, upperBound or lowerBound instantiated to either of the types Foo or Bar.</div><div><br></div><div>A solution is to apply the INCOHERENT pragma to the instances at lines 11, 14 and 17. Reading over section 10.8.3.6. Overlapping instances in the GHC User Guide, I believe I understand. (Is there a better solution?)</div><div><br></div><div>In the paste, I have INCOHERENT pragmas only at lines 11 and 17. This gives me the following behaviour in ghci:</div><div><ol><li>minBound, maxBound, upperBound and lowerBound instantiated to type Foo all function as expected, evaluating to the appropriate lower or upper bound.<br></li><li>upperBound and maxBound instantiated at Bar give overlapping instance errors for UpperBounded, as expected.</li><li>lowerBound :: Bar evaluates to C, as expected.</li><li>minBound :: Bar gives an overlapping instance error for UpperBounded:</li></ol><div><span style="font-family:monospace"><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">*UpperLowerBounded> minBound :: Bar
</span><br>
<br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)"><interactive>:141:1: </span><span style="font-weight:bold;color:rgb(255,84,84);background-color:rgb(255,255,255)">error:</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">    • Overlapping instances for UpperBounded Bar</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">        arising from a use of ‘minBound’</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">      Matching instances:</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">        instance [safe] Bounded a => UpperBounded a</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">          -- Defined at UpperLowerBounded.hs:14:10</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">        instance [safe] UpperBounded Bar -- Defined at UpperLowerBounded.hs:31:10</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">    • In the expression: minBound :: Bar</span><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br><span style="font-weight:bold;color:rgb(0,0,0);background-color:rgb(255,255,255)">      In an equation for ‘it’: it = minBound :: Bar</span><br><span style="color:rgb(0,0,0);background-color:rgb(255,255,255)">
</span><br></span><br></div></div><div>It's #4 that I don't understand. An explanation would be very much appreciated. (Also, what's a [safe] instance?)</div><div><br></div><div>Regards,</div><div>Graham</div><div><br></div></div>
<br>______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br></div>
______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
</blockquote></div>
</div></div><br>______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br></div>