(* Fifth version of Rational that reimplements the type using an int * int. This change would be invisible (opaque) to a client of the structure. *) module type RATIONAL = sig type rational exception Not_a_rational val make_fraction : int * int -> rational val whole : int -> rational val add : rational * rational -> rational val to_string : rational -> string end module Rational : RATIONAL = struct type rational = int * int exception Not_a_rational let rec gcd(x, y) = if x < 0 || y < 0 then gcd(abs(x), abs(y)) else if y = 0 then x else gcd(y, x mod y) let rec reduce_rational(a, b) = if b < 0 then reduce_rational(-a, -b) else let d = gcd(a, b) in (a/d, b/d) let make_fraction(a, b) = if b = 0 then raise Not_a_rational else reduce_rational(a, b) let whole(a) = (a, 1) let add((a, b), (c, d)) = reduce_rational(a * d + c * b, b * d) let to_string(a, b) = if b = 1 then string_of_int(a) else string_of_int(a) ^ "/" ^ string_of_int(b) end