diff --git a/src/Data/Ratio.idr b/src/Data/Ratio.idr index 63ef2a0..b7882f0 100644 --- a/src/Data/Ratio.idr +++ b/src/Data/Ratio.idr @@ -2,28 +2,45 @@ module Data.Ratio infix 10 // +||| Ratio types, represented by a numerator and denominator of type `a`. +||| +||| Most numeric operations require an instance `Integral a` in order to +||| simplify the returned ratio and reduce storage space. export record Ratio a where constructor MkRatio nm, dn : a +||| Rational numbers, represented as a ratio between +||| two arbitrary-precision integers. +||| +||| Rationals can be constructed using `//`. public export Rational : Type Rational = Ratio Integer +-- This function is almost always total; after all, it's a fairly standard +-- implementation of Euclid's algorithm. Unfortunately, we can't _guarantee_ +-- it's total without knowing exactly what the implementation of `Integral a` is, +-- so using an `assert_total` here would be potentially unsafe. The only option +-- is to mark this function, and by extention `reduce`, as non-total. gcd : (Eq a, Integral a) => a -> a -> a gcd x y = if x == 0 then y else if y == 0 then x else gcd y (x `mod` y) +||| Reduce a ratio by dividing both components by their common factor. Most +||| operations automatically reduce the returned ratio, so explicitly calling +||| this function is usually unnecessary. export reduce : (Eq a, Integral a) => Ratio a -> Ratio a reduce (MkRatio n d) = let g = gcd n d in MkRatio (n `div` g) (d `div` g) +||| Construct a ratio of two values. export partial (//) : (Eq a, Integral a) => a -> a -> Ratio a n // d = case d /= 0 of @@ -31,18 +48,24 @@ n // d = case d /= 0 of namespace Ratio + ||| Return the numerator of the fraction in reduced form. export %inline numer : Ratio a -> a numer = nm + ||| Return the numerator of the fraction in reduced form. export %inline (.numer) : Ratio a -> a (.numer) = nm + ||| Return the denominator of the fraction in reduced form. + ||| This value is guaranteed to always be positive. export %inline denom : Ratio a -> a denom = dn + ||| Return the denominator of the fraction in reduced form. + ||| This value is guaranteed to always be positive. export %inline (.denom) : Ratio a -> a (.denom) = dn