(* For ML lecture 4 *) (* Question 2: simple bank account module *) module BankImpl = struct type account = string * int ref exception Underflow exception InvalidPassword exception InvalidOperation let accounts = ref [] let banktreasure = ref 10000 let do_cashier (_, cur : account) amount = cur := !cur + amount; banktreasure := !banktreasure + amount let pass_check (p, _ : account) pass = if (p = pass) then () else raise InvalidPassword let balance_int (_, cur : account) = !cur let new_account password initial = if initial <= 0 then raise InvalidOperation else begin let instance = (password, ref 0 : account) in accounts := instance :: !accounts; do_cashier instance initial; instance end let balance acc pass = pass_check acc pass; balance_int acc let deposit acc amount = if amount <= 0 then raise InvalidOperation else do_cashier acc amount let withdraw acc pass amount = if amount <= 0 then raise InvalidOperation else begin pass_check acc pass; if balance_int acc < amount then raise Underflow else do_cashier acc (-amount) end let bank_statistics () = List.length !accounts, !banktreasure end (* # open BankImpl;; # let a1 = new_account "pass1" 50;; val a1 : BankImpl.account = ("pass1", {contents = 50}) # bank_statistics ();; - : int * int = (1, 10050) # withdraw a1 "foobar" 30;; Exception: BankImpl.InvalidPassword. # withdraw a1 "pass1" 30;; - : unit = () # withdraw a1 "pass1" 100;; Exception: BankImpl.Underflow. # deposit a1 50;; - : unit = () # balance a1 "pass1";; - : int = 70 # let a2 = new_account "pass2" 1000;; val a2 : BankImpl.account = ("pass2", {contents = 1000}) # bank_statistics ();; - : int * int = (2, 11070) *)