std.rational
Rationals: exact fractions of integers, as Racket’s exact numbers are,
of any size, as an Int is. A rational is kept in its lowest terms,
its denominator above 0, so two equal ones are the same: over 2 4
is over (-1) (-2), one half. Its instances are the prelude’s
operators at Rational — x + y, x * y, -x, x < y, max x y,
x / y (by 0, 0, as the prelude’s / is) — and divide divides it
by what is not 0, over makes one and toFloat is the float nearest
it. Import it by a name, import std.rational as Rational, as
toFloat is the prelude’s of an Int.
import std.rational as Rational
-- | 1 + 1/2 + 1/3 + ... + 1/n-- | >>> show (harmonic 4)-- | "25/12"harmonic : Int -> Rational.Rationalharmonic n = List.foldl (\acc k -> acc + fromMaybe (Rational.fromInt 0) (Rational.over 1 k)) (Rational.fromInt 0) (List.range 1 n)Rational
data RationalA rational: its numerator and its denominator, in its lowest terms
(no integer above 1 divides both) and the denominator above 0 — as
over makes it, which a rational made by the tag must be too.
over
over : Int -> Int -> Maybe Rationaln over d, in its lowest terms; over 0, nothing.
>>> over 6 (-4)Just (MkRational (-3) 2)>>> over 1 0NothingfromInt
fromInt : Int -> RationalThe integer, over 1.
numerator
numerator : Rational -> IntIts numerator, of its lowest terms: of the sign of the rational.
denominator
denominator : Rational -> IntIts denominator, of its lowest terms: above 0.
>>> maybe 0 denominator (over 6 (-4))2toFloat
toFloat : Rational -> Float64The float nearest it, correctly rounded: a tie to the even, as
std.math’s fromDecimal rounds a decimal — beyond the greatest
float, an infinity, and below half the least, 0.0 (of its sign).
>>> List.map toFloat ([fromInt 3, MkRational 1 3, MkRational (-1) 10] : List Rational)[3.0, 0.3333333333333333, -0.1]>>> List.map toFloat ([MkRational 1 (Math.tenTo 400), MkRational (Math.tenTo 400) 1] : List Rational)[0.0, Infinity]divide
divide : Rational -> Rational -> Maybe RationalThe first divided by the second; by 0, nothing.
>>> divide (MkRational 1 2) (MkRational (-3) 4)Just (MkRational (-2) 3)>>> divide (MkRational 1 2) (fromInt 0)NothinginstanceEqualityRational
instance instanceEqualityRational : Equality RationalEqual as fractions: in their lowest terms, of the same terms.
instanceOrderRational
instance instanceOrderRational : Order Rational>>> List.map (\p -> compare (fst p) (snd p)) ([MkPair (MkRational 1 3) (MkRational 1 2), MkPair (MkRational (-1) 2) (MkRational (-2) 3)] : List (Pair Rational Rational))Cons LT (Cons GT Nil)instanceAdditionRational
instance instanceAdditionRational : Addition RationalinstanceSubtractionRational
instance instanceSubtractionRational : Subtraction Rational>>> (MkRational 1 2 + MkRational 1 3 - MkRational 1 6 : Rational)MkRational 2 3instanceMultiplicationRational
instance instanceMultiplicationRational : Multiplication Rational>>> (MkRational 2 3 * MkRational (-9) 4 : Rational)MkRational (-3) 2instanceDivisionRational
instance instanceDivisionRational : Division RationalDivision, total, as the prelude’s / is: by 0, 0 (divide says
nothing instead).
>>> ([MkRational 1 2 / MkRational (-3) 4, MkRational 1 2 / fromInt 0] : List Rational)Cons (MkRational (-2) 3) (Cons (MkRational 0 1) Nil)instanceNegationRational
instance instanceNegationRational : Negation Rational>>> (-(MkRational 1 2) : Rational)MkRational (-1) 2instanceIsZeroRational
instance instanceIsZeroRational : IsZero RationalinstanceDebugRational
instance instanceDebugRational : Debug RationalAs its tag rebuilds it: MkRational 3 4, a negative numerator in
parentheses.
>>> debug (MkRational (-3) 4 : Rational) ^ " " ^ debug (fromInt 2)"MkRational (-3) 4 MkRational 2 1"instanceShowRational
instance instanceShowRational : Show RationalAs a reader writes it, as Racket’s: 3/4, -3/4, and an integer
alone, 2.
>>> show (MkRational (-3) 4 : Rational) ^ " " ^ show (fromInt 2)"-3/4 2"