signature RAT = sig (* types *) type rat (* abstract *) (* type rat = int * int (* concrete *) *) (* conversions *) val rat : int * int -> rat (* may raise Div *) val fraction : rat -> int * int val toString : rat -> string (* operations *) val plus : rat * rat -> rat val minus : rat * rat -> rat val times : rat * rat -> rat val divide : rat * rat -> rat (* may raise Div *) val equal : rat * rat -> bool val less : rat * rat -> bool val greater : rat * rat -> bool end; (* signature RAT *) structure Rat :> RAT = (* opaque *) (* structure Rat : RAT = (* transparent *) *) struct (* Invariants: *) (* rationals are represented as a pair of ints, (nem, den) *) (* the fraction nem/den is in fully reduced form *) (* den > 0 *) (* (0, 1) is the unique form for 0 *) type rat = int * int (* val reduce : int * int -> rat *) (* d <> 0 *) fun reduce (0, d) = (0, 1) | reduce (n, d) = let val g = gcd (n, d) in (n div g, d div g) end fun rat (n, 0) = raise Div | rat (n, d) = reduce (n, d) fun fraction r = r fun toString (n, 1) = Int.toString(n) | toString (n, m) = Int.toString(n) ^ "/" ^ Int.toString(m) (* a/b + c/d = (a*d+c*b/(b*d)) *) fun plus ((n1, d1), (n2, d2)) = reduce ( n1*d2 + n2*d1, d1*d2 ) fun minus (r1, (n2, d2)) = plus (r1, (~n2, d2)) fun times ((n1, d1), (n2, d2)) = reduce (n1*n2, d1*d2) fun divide (r1, (0, _)) = raise Div | divide (r1, (n2, d2)) = times (r1, (d2, n2)) fun equal ((n1, d1), (n2, d2)) = (n1 = n2) andalso (d1 = d2) fun less ((n1, d1), (n2, d2)) = (n1*d2) < (n2*d1) fun greater ((n1, d1), (n2, d2)) = (n1*d2) > (n2*d1) end; (* structure Rat *)