<div dir="ltr">Yes, I see <a href="http://support.hfm.io/1.0/api/haskell2010-1.1.2.0/Data-Ratio.html">here</a> that the module Data.Ratio exports this<div><br></div><div><font face="monospace">module  Data.Ratio (<br>    Ratio, Rational, (%), numerator, denominator, approxRational ) where</font></div><div><font face="monospace"><br></font></div><div><font face="arial, sans-serif">which doesn't include </font><font face="monospace">:%</font><font face="arial, sans-serif">.  But then I see </font><font face="monospace">numerator</font><font face="arial, sans-serif"> and </font><font face="monospace">denominator</font><font face="arial, sans-serif"> which do have </font><font face="monospace">:%</font><font face="arial, sans-serif">. But then to use them, this, e.g., won't work</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="monospace">numerator (60 20)</font></div><div><br></div><div>It needs the <font face="monospace">%</font></div><div><br></div><div><font face="monospace">numerator (60 % 20)</font></div><div><font face="monospace"><br></font></div><div><font face="arial, sans-serif">So internally, </font><font face="monospace">:%</font><font face="arial, sans-serif"> is used, but users can never use </font><font face="monospace">:%</font><font face="arial, sans-serif">, only </font><font face="monospace">%</font><font face="arial, sans-serif">, which sends things through </font><font face="monospace">reduce</font><font face="arial, sans-serif"> first. I could write my own version of </font><font face="monospace">Ratio</font><font face="arial, sans-serif"> that didn't hide </font><font face="monospace">:<some symbol></font><font face="arial, sans-serif"> and that would be okay. </font><span style="font-family:arial,sans-serif">Have I got this right?</span><br><div><br></div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 20, 2021 at 4:37 PM Bob Ippolito <<a href="mailto:bob@redivi.com">bob@redivi.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">Yes, the (%) function is a smart constructor for Data.Ratio because the (:%) constructor is not exported. Other examples of this smart constructor technique would be modules like Data.Set or Data.Map.<div><br></div><div>A smart constructor means that the module that defines the type does not export its data constructor(s), making the implementation details opaque, generally because the author wanted to be able to make assumptions about the implementation that are not enforced by the type system. In this case, they wanted all Ratio to be in reduced form. This makes many operations faster or trivial, e.g. implementing Eq only requires comparing the numerators and denominators. More information about the technique is here: <a href="https://wiki.haskell.org/Smart_constructors" target="_blank">https://wiki.haskell.org/Smart_constructors</a><div><br></div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 20, 2021 at 2:17 PM Galaxy Being <<a href="mailto:borgauf@gmail.com" target="_blank">borgauf@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">... does the last question have to do with a "smart constructor" by chance? If so, how?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 20, 2021 at 3:42 PM Galaxy Being <<a href="mailto:borgauf@gmail.com" target="_blank">borgauf@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">I'm investigating rational numbers with Haskell. This is the source I've found<div><br></div><div><font face="monospace">data Ratio a = !a :% !a deriving (Eq)<br></font></div><div><font face="monospace"><br></font></div><div><font face="monospace">reduce ::  (Integral a) => a -> a -> Ratio a<br>{-# SPECIALISE reduce :: Integer -> Integer -> Rational #-}<br>reduce _ 0              =  ratioZeroDenominatorError<br>reduce x y              =  (x `quot` d) :% (y `quot` d)<br>                           where d = gcd x y<br>(%) :: (Integral a) => a -> a -> Ratio a<br>x % y =  reduce (x * signum y) (abs y)</font></div><div><font face="monospace"><br></font></div><div><font face="arial, sans-serif">The </font><font face="monospace">Ratio</font><font face="arial, sans-serif"> data type would seem to be a parameterized type with two parameters of the same type that must be "settled" in that they're not to be lazily dealt with. Then the </font><font face="monospace">:% </font><font face="arial, sans-serif">is the data constructor, the </font><font face="monospace">:</font><font face="arial, sans-serif"> meaning it's a data constructor and not just an operation function. So this could have been</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="monospace">data Ratio a = :% !a !a deriving (Eq)</font></div><div><br></div><div>correct? But then what confuses me is in reduce, why <br clear="all"><div><br></div><div><font face="monospace">reduce x y  =  (x `quot` d) :% (y `quot` d)</font><br></div><div><br></div><div>and not just <font face="monospace">%</font>? We have<font face="monospace"> :%</font> defined in the data type and then <font face="monospace">(%)</font> defined as a function. What is going on here?</div><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div>⨽<br></div>Lawrence Bottorff<div>Grand Marais, MN, USA</div><div><a href="mailto:borgauf@gmail.com" target="_blank">borgauf@gmail.com</a></div></div></div></div></div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div>⨽<br></div>Lawrence Bottorff<div>Grand Marais, MN, USA</div><div><a href="mailto:borgauf@gmail.com" target="_blank">borgauf@gmail.com</a></div></div></div>
_______________________________________________<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-bin/mailman/listinfo/beginners</a><br>
</blockquote></div>
_______________________________________________<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-bin/mailman/listinfo/beginners</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>⨽<br></div>Lawrence Bottorff<div>Grand Marais, MN, USA</div><div><a href="mailto:borgauf@gmail.com" target="_blank">borgauf@gmail.com</a></div></div></div>