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