< Back

2014-02-03

Is there a user-noticeable difference in how exceptions behave in SML vs OCaml?

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:

1 in SML

$ 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:

1 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 = 
#
  exception E;;
exception E
#
  let e2 = E;;
val e2 : exn = E
#
  let is_e2 = function
    | E -> true
    | _ -> false;;
val is_e2 : exn -> bool = 
#
  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:

2 in SML

$ 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:

2 in OCaml, A

$ 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:

2 in OCaml, B

#
  let f () =
    let module M = struct exception E end in
    (M.E, function M.E -> true | _ -> false)
  ;;
val f : unit -> exn * (exn -> bool) = 
#
  let e1, is_e1 = f ();;
val e1 : exn = E
val is_e1 : exn -> bool = 
#
  let e2, is_e2 = f ();;
val e2 : exn = E
val is_e2 : exn -> bool = 
#
  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.

Am I wrong? Please let me know!