[Haskell-beginners] Ratio data constructor

Galaxy Being borgauf at gmail.com
Tue Jul 20 22:09:56 UTC 2021


Yes, I see here
<http://support.hfm.io/1.0/api/haskell2010-1.1.2.0/Data-Ratio.html> that
the module Data.Ratio exports this

module  Data.Ratio (
    Ratio, Rational, (%), numerator, denominator, approxRational ) where

which doesn't include :%.  But then I see numerator and denominator which
do have :%. But then to use them, this, e.g., won't work

numerator (60 20)

It needs the %

numerator (60 % 20)

So internally, :% is used, but users can never use :%, only %, which sends
things through reduce first. I could write my own version of Ratio that
didn't hide :<some symbol> and that would be okay. Have I got this right?



On Tue, Jul 20, 2021 at 4:37 PM Bob Ippolito <bob at redivi.com> wrote:

> 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.
>
> 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: https://wiki.haskell.org/Smart_constructors
>
>
>
> On Tue, Jul 20, 2021 at 2:17 PM Galaxy Being <borgauf at gmail.com> wrote:
>
>> ... does the last question have to do with a "smart constructor" by
>> chance? If so, how?
>>
>> On Tue, Jul 20, 2021 at 3:42 PM Galaxy Being <borgauf at gmail.com> wrote:
>>
>>> I'm investigating rational numbers with Haskell. This is the source I've
>>> found
>>>
>>> data Ratio a = !a :% !a deriving (Eq)
>>>
>>> reduce ::  (Integral a) => a -> a -> Ratio a
>>> {-# SPECIALISE reduce :: Integer -> Integer -> Rational #-}
>>> reduce _ 0              =  ratioZeroDenominatorError
>>> reduce x y              =  (x `quot` d) :% (y `quot` d)
>>>                            where d = gcd x y
>>> (%) :: (Integral a) => a -> a -> Ratio a
>>> x % y =  reduce (x * signum y) (abs y)
>>>
>>> The Ratio 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 :% is the data constructor, the :
>>> meaning it's a data constructor and not just an operation function. So this
>>> could have been
>>>
>>> data Ratio a = :% !a !a deriving (Eq)
>>>
>>> correct? But then what confuses me is in reduce, why
>>>
>>> reduce x y  =  (x `quot` d) :% (y `quot` d)
>>>
>>> and not just %? We have :% defined in the data type and then (%)
>>> defined as a function. What is going on here?
>>>
>>> --
>>>>>> Lawrence Bottorff
>>> Grand Marais, MN, USA
>>> borgauf at gmail.com
>>>
>>
>>
>> --
>>>> Lawrence Bottorff
>> Grand Marais, MN, USA
>> borgauf at gmail.com
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>


-- 
⨽
Lawrence Bottorff
Grand Marais, MN, USA
borgauf at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20210720/9ef0d003/attachment.html>


More information about the Beginners mailing list