
On Tue, Jul 20, 2021 at 1:43 PM Galaxy Being
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
The type has one parameter a, the (:%) constructor has two arguments (both of type a).
data Ratio a = :% !a !a deriving (Eq)
You always need to use parentheses around an infix operator to use it in prefix, just like you need backticks around a function to use it as infix (like `quot` in the implementation of reduce). 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?
The function (%) uses reduce in its definition, the equation would never terminate due to infinite recursion if the function (%) was used instead of the constructor (:%). -bob