```//
// Course: BU CAS CS 520, Fall 2010
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Lecture on Tuesday, Nov 30, 2010
//

(* ****** ****** *)

datatype tree = E of () | B of (tree, tree)

(* ****** ****** *)

(*
//
// HX: Python-style :)
//
extern fun ht (t: tree): int
fun isPerfect (t: tree): bool =
case+ t of
| B (tl, tr) => isPerfect (tl) andalso isPerfect (tr) andalso (ht(tl) = ht(tr))
| E () => true
// end of [isPerfect]
*)

(*
//
// HX: C-style :)
//
fun isPerfect (t: tree): bool = let
fun aux (t: tree): int =
case+ t of
| B (tl, tr) => let
val hl = aux (tl)
in
if hl >= 0 then let
val hr = aux (tr) in if hl=hr then hl+1 else ~1
end else ~1
end // end of [B]
| E () => 0
in
aux (t) >= 0
end // end of [isPerfect]
*)

(*
//
// HX: A functional monadic style
//
fun isPerfect
(t: tree): bool = let
fun aux (t: tree): Option (int) =
case+ t of
| B (tl, tr) => (case+ aux(tl) of
| Some hl => (case+ aux(tr) of
| Some hr => if hl=hr then Some (hl+1) else None ()
| None () => None ()
)
| None () => None ()
) // end of [B]
| E () => Some (0)
in
case+ aux (t) of | Some _ => true | None () => false
end // end of [isPerfect]
*)

(*
// HX: An example of proper use of exception
*)

fun isPerfect
(t: tree): bool = let
exception NotPerfect of ()
fun aux (t: tree): int =
case+ t of
| B (tl, tr) => let
val hl = aux (tl) and hr = aux (tr)
in
if hl = hr then hl + 1 else \$raise (NotPerfect)
end // end of [B]
| E () => 0
// end of [aux]
in
try
let val _ = aux (t) in true end
with
~NotPerfect () => false
// end of [try]
end // end of [isPerfect]

(* ****** ****** *)

(* end of [exception.dats] *)

```