Example:
1 div 0 => raise Div
(case [1] of [] => 0) => raise Match
raise Div
raise Fail "I failed"
Types of exception (actually the constructors): because they are value
Div: exn
Match: exn
Fail: string -> exn
exception Divide
exception Rdivide of real
Divide: exn
Rdivide: real -> exn
datatype 'a option = NONE | SOME of 'a
NONE: 'a option
SOME: 'a -> 'a option
Having a type does not mean valuable, so raise Div
has no value and has type 'a
, raise
is not a function but a keyword, that applies after functions. Div
is a value.
if e0
loop, exception handle loop
if e0
has value, exception handle has original value
if e0
raise exception, exception handle assign to new value based on match. if there is no match, keep raise the same exception upward
((e0) handle p1 => e1 | p2 => e2)
(*threat (int * int) -> (int * int) -> bool *)
fun threat (x, y) (a, b) = x = a
orelse y = b
orelse x-y=a-b
orelse x+y=a+b
(*confict: (int * int) -> (int * int) list -> bool *)
fun conflict p = List.exists (threat p)
USING EXCEPTION
(*addqueens: int * int * (int * int) list -> (int * int) list
REQUIRES: n > 0, 1 <= i <= n. Q non-conflicting
ENSURES: addqueens(n, i, Q) extend Q, else raise Conflict
*)
fun addqueens (i, n, Q)
= let (*try: int -> (int * int) list*)
fun try j
= (if conflict (i, j) Q
then raise Conflict
else if i = n
then (i, j) :: Q
else addqueens(i+1, n, (i, j) Q)) handel Conflict => if j = n then raise Conflict else try (j+1)
in
try 1
end
(*queens: int -> (int * int) list option *)
fun queens n = (SOME (addqueens (1, n, []))) handle Conflict => NONE
USING CONTINUATION
(*addqueens': int * int * (int * int) list -> ((int * int) list -> 'a) -> (unit -> 'a) -> 'a *)
fun addqueens' (i, n, Q) sk fk
= let
fun try j
= let
fun fk' () = if j=n then fk() else try (j+1)
in
if conflict (i, j) Q then fk' ()
else if i=n then sk((i, j) : Q)
else addqueens'(i+1, n, (i, j)::Q) sk fk'
end
in
try 1
end
(*queens: int -> (int * int) list option *)
fun queen n = addqueens' (1, n, []) SOME (fn () => NONE)
USING NEITHER
fun addqueens'' (i, n, Q)
= let (*try: int -> (int * int) list option*)
fun try j
= (case (if conflict (i, j) Q
then NONE
else if i = n
then SOME ((i, j) :: Q)
else addqueens(i+1, n, (i, j) Q)) of
NONE => if j = n then NONE else try (j+1)
| SOME Q' => SOME Q')
in
try 1
end
fun queen n = addqueens'' (i, n, [])
Table of Content