about
Bob Harper has mentioned that exceptions in OCaml aren't done right, that SML's dynamic classification is uniquely superior. This intrigued me, so I set out to find some concrete examples demonstrating this uniqueness. I was not able to.
Here're a couple of examples demonstrating the generative semantics of SML exceptions (derived from http://mlton.org/GenerativeException followed by their analogues in OCaml:
$ ledit sml
Standard ML of New Jersey v110.76 [built: Tue Jan 7 12:24:04 2014]
-
- exception E;
exception E
-
- val e1 = E;
val e1 = E(-) : exn
-
- fun isE1 E = true
= | isE1 _ = false;
val isE1 = fn : exn -> bool
-
- exception E;
exception E
-
- val e2 = E;
val e2 = E(-) : exn
-
- fun isE2 E = true
= | isE2 _ = false;
val isE2 = fn : exn -> bool
-
- isE1 e1;
val it = true : bool
- isE1 e2;
val it = false : bool
- isE2 e1;
val it = false : bool
- isE2 e2;
val it = true : bool
-
However, this behavior is identical in OCaml:
$ ledit ocaml
OCaml version 4.01.0
#
exception E;;
exception E
#
let e1 = E;;
val e1 : exn = E
#
let is_e1 = function
| E -> true
| _ -> false;;
val is_e1 : exn -> bool = <fun>
#
exception E;;
exception E
#
let e2 = E;;
val e2 : exn = E
#
let is_e2 = function
| E -> true
| _ -> false;;
val is_e2 : exn -> bool = <fun>
#
is_e1 e1;;
- : bool = true
# is_e1 e2;;
- : bool = false
# is_e2 e1;;
- : bool = false
# is_e2 e2;;
- : bool = true
#
The first difference seems to appear with this example:
$ ledit sml
Standard ML of New Jersey v110.76 [built: Tue Jan 7 12:24:04 2014]
-
- fun f () =
= let
= exception E
= in
= (E, fn E => true | _ => false)
= end;
val f = fn : unit -> exn * (exn -> bool)
-
- val (e1, isE1) = f ();
val e1 = E(-) : exn
val isE1 = fn : exn -> bool
- val (e2, isE2) = f ();
val e2 = E(-) : exn
val isE2 = fn : exn -> bool
-
- isE1 e1;
val it = true : bool
- isE1 e2;
val it = false : bool
- isE2 e1;
val it = false : bool
- isE2 e2;
val it = true : bool
-
Whereas in OCaml an analogous definition does not seem to be possible:
$ ledit ocaml
OCaml version 4.01.0
# let f () =
let exception E in
(E, function E -> true | _ -> false)
;;
Error: Syntax error
#
But with some local module hackery, we can:
#
let f () =
let module M = struct exception E end in
(M.E, function M.E -> true | _ -> false)
;;
val f : unit -> exn * (exn -> bool) = <fun>
#
let e1, is_e1 = f ();;
val e1 : exn = E
val is_e1 : exn -> bool = <fun>
#
let e2, is_e2 = f ();;
val e2 : exn = E
val is_e2 : exn -> bool = <fun>
#
is_e1 e1;;
- : bool = true
# is_e1 e2;;
- : bool = false
#
is_e2 e1;;
- : bool = false
# is_e2 e2;;
- : bool = true
#
Which seems to behave identically to SML.