Data.Ratio

haskell2010-1.1.2.0: Compatibility with Haskell 2010

Safe Haskell | Safe
Language | Haskell2010

Data.Ratio

Contents

- Specification

Synopsis

- data Ratio a :: * -> *
- type Rational = Ratio Integer
- (%) :: Integral a => a -> a -> Ratio a
- numerator :: Integral a => Ratio a -> a
- denominator :: Integral a => Ratio a -> a
- approxRational :: RealFrac a => a -> a -> Rational

# Documentation

data Ratio a :: * -> * Source

Rational numbers, with numerator and denominator of some `Integral` type.

Instances

Integral a => Enum (Ratio a) |
Eq a => Eq (Ratio a) |
Integral a => Fractional (Ratio a) |
Integral a => Num (Ratio a) |
Integral a => Ord (Ratio a) |
(Integral a, Read a) => Read (Ratio a) |
Integral a => Real (Ratio a) |
Integral a => RealFrac (Ratio a) |
(Integral a, Show a) => Show (Ratio a) |

type Rational = Ratio Integer Source

Arbitrary-precision rational numbers, represented as a ratio of two `Integer` values. A rational number may be constructed using the `%` operator.

(%) :: Integral a => a -> a -> Ratio a infixl 7 Source

Forms the ratio of two integral numbers.

numerator :: Integral a => Ratio a -> a Source

Extract the numerator of the ratio in reduced form: the numerator and denominator have no common factor and the denominator is positive.

denominator :: Integral a => Ratio a -> a Source

Extract the denominator of the ratio in reduced form: the numerator and denominator have no common factor and the denominator is positive.

approxRational :: RealFrac a => a -> a -> Rational Source

`approxRational`, applied to two real fractional numbers `x` and `epsilon`, returns the simplest rational number within `epsilon` of `x`. A rational number `y` is said to be simpler than another `y'` if

- ``abs` (`numerator` y) <= `abs` (`numerator` y')`, and
- ``denominator` y <= `denominator` y'`.

Any real interval contains a unique simplest rational; in particular, note that `0/1` is the simplest rational of all.

# Specification

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

    infixl 7  %

    ratPrec = 7 :: Int

    data  (Integral a)      => Ratio a = !a :% !a  deriving (Eq)
    type  Rational          =  Ratio Integer

    (%)                     :: (Integral a) => a -> a -> Ratio a
    numerator, denominator  :: (Integral a) => Ratio a -> a
    approxRational          :: (RealFrac a) => a -> a -> Rational

    -- "reduce" is a subsidiary function used only in this module.
    -- It normalises a ratio by dividing both numerator
    -- and denominator by their greatest common divisor.
    --
    -- E.g., 12 `reduce` 8    ==  3 :%   2
    --       12 `reduce` (-8) ==  3 :% (-2)

    reduce _ 0              =  error "Data.Ratio.% : zero denominator"
    reduce x y              =  (x `quot` d) :% (y `quot` d)
                               where d = gcd x y

    x % y                   =  reduce (x * signum y) (abs y)

    numerator (x :% _)      =  x

    denominator (_ :% y)    =  y

    instance  (Integral a)  => Ord (Ratio a)  where
        (x:%y) <= (x':%y')  =  x * y' <= x' * y
        (x:%y) <  (x':%y')  =  x * y' <  x' * y

    instance  (Integral a)  => Num (Ratio a)  where
        (x:%y) + (x':%y')   =  reduce (x*y' + x'*y) (y*y')
        (x:%y) * (x':%y')   =  reduce (x * x') (y * y')
        negate (x:%y)       =  (-x) :% y
        abs (x:%y)          =  abs x :% y
        signum (x:%y)       =  signum x :% 1
        fromInteger x       =  fromInteger x :% 1

    instance  (Integral a)  => Real (Ratio a)  where
        toRational (x:%y)   =  toInteger x :% toInteger y

    instance  (Integral a)  => Fractional (Ratio a)  where
        (x:%y) / (x':%y')   =  (x*y') % (y*x')
        recip (x:%y)        =  y % x
        fromRational (x:%y) =  fromInteger x :% fromInteger y

    instance  (Integral a)  => RealFrac (Ratio a)  where
        properFraction (x:%y) = (fromIntegral q, r:%y)
                                where (q,r) = quotRem x y

    instance  (Integral a)  => Enum (Ratio a)  where
        succ x           =  x+1
        pred x           =  x-1
        toEnum           =  fromIntegral
        fromEnum         =  fromInteger . truncate        -- May overflow
        enumFrom         =  numericEnumFrom               -- These numericEnumXXX functions
        enumFromThen     =  numericEnumFromThen   -- are as defined in Prelude.hs
        enumFromTo       =  numericEnumFromTo     -- but not exported from it!
        enumFromThenTo   =  numericEnumFromThenTo

    instance  (Read a, Integral a)  => Read (Ratio a)  where
        readsPrec p  =  readParen (p > ratPrec)
                                  (\r -> [(x%y,u) | (x,s)   <- readsPrec (ratPrec+1) r,
                                                    ("%",t) <- lex s,
                                                    (y,u)   <- readsPrec (ratPrec+1) t ])

    instance  (Integral a)  => Show (Ratio a)  where
        showsPrec p (x:%y)  =  showParen (p > ratPrec)
                                  showsPrec (ratPrec+1) x .
                                  showString " % " .
                                  showsPrec (ratPrec+1) y)

    approxRational x eps    =  simplest (x-eps) (x+eps)
            where simplest x y | y < x      =  simplest y x
                               | x == y     =  xr
                               | x > 0      =  simplest' n d n' d'
                               | y < 0      =  - simplest' (-n') d' (-n) d
                               | otherwise  =  0 :% 1
                                            where xr@(n:%d) = toRational x
                                                  (n':%d')  = toRational y

                  simplest' n d n' d'       -- assumes 0 < n%d < n'%d'
                            | r == 0     =  q :% 1
                            | q /= q'    =  (q+1) :% 1
                            | otherwise  =  (q*n''+d'') :% n''
                                         where (q,r)      =  quotRem n d
                                               (q',r')    =  quotRem n' d'
                                               (n'':%d'') =  simplest' d' r' d r