signature Rational = sig type R exception DenomIsZero val makerat: int*int -> R val numer: R -> int val denom: R -> int val add: R*R -> R end; structure Rat : Rational = struct exception DenomIsZero; datatype R = ratify of int*int; fun gcd(a,b) = if (b=0) then a else gcd(b,a mod b); fun makerat(p,q) = if (q=0) then raise DenomIsZero else let val g = gcd(p,q); in ratify(p div g,q div g) end; fun numer(ratify(p,_)) = p; fun denom(ratify(_,q)) = q; fun add(a:R,b:R) = makerat(numer(a)*denom(b)+numer(b)*denom(a),denom(a)*denom(b)); end;