CS 312 Recitation 8
More Data Abstractions
An Abstraction for Rational Numbers
signature FRACTION = sig
type fraction
val make : int -> int -> fraction
val numerator : fraction -> int
val denominator : fraction -> int
val toString : fraction -> string
val toReal : fraction -> real
val add : fraction -> fraction -> fraction
val mul : fraction -> fraction -> fraction
end
structure Fraction1 :> FRACTION =
struct
type fraction = { num:int, denom:int }
fun make (n:int) (d:int) = {num=n, denom=d}
fun numerator(x:fraction):int = #num x
fun denominator(x:fraction):int = #denom x
fun toString(x:fraction):string =
(Int.toString (numerator x)) ^ "/" ^
(Int.toString (denominator x))
fun toReal(x:fraction):real =
(Real.fromInt (numerator x)) / (Real.fromInt (denominator x))
fun mul (x:fraction) (y:fraction) : fraction =
make ((numerator x)*(numerator y))
((denominator x)*(denominator y))
fun add (x:fraction) (y:fraction) : fraction =
make ((numerator x)*(denominator y) +
(numerator y)*(denominator x))
((denominator x)*(denominator y))
end
A Better Abstraction for Rational Numbers
structure Fraction2 :> FRACTION =
struct
type fraction = { num:int, denom:int }
fun gcd (x:int) (y:int) : int =
if (x = y) then x
else if (x < y) then gcd x (y - x)
else gcd (x - y) y
exception BadDenominator
fun make (n:int) (d:int) : fraction =
if (d = 0) then raise BadDenominator
else let val g = gcd (abs n) (abs d)
val n2 = n div g
val d2 = d div g
in
if (d2 < 0) then {num = ~n2, denom = ~d2}
else {num = n2, denom = d2}
end
fun numerator(x:fraction):int = #num x
fun denominator(x:fraction):int = #denom x
fun toString(x:fraction):string =
(Int.toString (numerator x)) ^ "/" ^
(Int.toString (denominator x))
fun toReal(x:fraction):real =
(Real.fromInt (numerator x)) / (Real.fromInt (denominator x))
fun mul (x:fraction) (y:fraction) : fraction =
make ((numerator x)*(numerator y))
((denominator x)*(denominator y))
fun add (x:fraction) (y:fraction) : fraction =
make ((numerator x)*(denominator y) +
(numerator y)*(denominator x))
((denominator x)*(denominator y))
end
A Dictionary Abstract Data Type
signature DICTIONARY =
sig
type key = string
type 'a dict
val make : unit -> 'a dict
val insert : 'a dict -> key -> 'a -> 'a dict
val lookup : 'a dict -> key -> 'a
exception NotFound
end
structure AssocList :> DICTIONARY =
struct
type key = string
type 'a dict = (key * 'a) list
fun make():'a dict = []
fun insert (d:'a dict) (k:key) (x:'a) : 'a dict = (k,x)::d
exception NotFound
fun lookup (d:'a dict) (k:key) : 'a =
case d of
[] => raise NotFound
| ((k',x)::rest) =>
if (k = k') then x
else lookup rest k
end
structure SortedAssocList :> DICTIONARY =
struct
type key = string
type 'a dict = (key * 'a) list
fun make():'a dict = []
fun insert (d:'a dict) (k:key) (x:'a) : 'a dict =
case d of
[] => (k,x)::nil
| (k',x')::rest =>
(case String.compare(k,k') of
GREATER => (k',x')::(insert rest k x)
| EQUAL => (k,x)::rest
| LESS => (k,x)::(k',x')::rest)
exception NotFound
fun lookup (d:'a dict) (k:key) : 'a =
case d of
[] => raise NotFound
| ((k',x)::rest) =>
(case String.compare(k,k') of
EQUAL => x
| LESS => raise NotFound
| GREATER => lookup rest k)
end
structure AssocTree :> DICTIONARY =
struct
type key = string
datatype 'a dict = Empty | Node of {key: key,datum: 'a,
left: 'a dict,right: 'a dict}
fun make():'a dict = Empty
fun insert (d:'a dict) (k:key) (x:'a) : 'a dict =
case d of
Empty => Node{key=k, datum=x, left=Empty, right=Empty}
| Node {key=k', datum=x', left=l, right=r} =>
(case String.compare(k,k') of
EQUAL =>
Node{key=k, datum=x, left=l, right=r}
| LESS =>
Node{key=k',datum=x',left=insert l k x,
right=r}
| GREATER =>
Node{key=k',datum=x',left=l,
right=insert r k x})
exception NotFound
fun lookup (d:'a dict) (k:key) : 'a =
case d of
Empty => raise NotFound
| Node{key=k',datum=x, left=l, right=r} =>
(case String.compare(k,k') of
EQUAL => x
| LESS => lookup l k
| GREATER => lookup r k)
end