4 In <:StandardML:Standard ML>, exception declarations are said to be
5 _generative_, because each time an exception declaration is evaluated,
6 it yields a new exception.
8 The following program demonstrates the generativity of exceptions.
14 fun isE1 (e: exn): bool =
20 fun isE2 (e: exn): bool =
24 fun pb (b: bool): unit =
25 print (concat [Bool.toString b, "\n"])
26 val () = (pb (isE1 e1)
32 In the above program, two different exception declarations declare an
33 exception `E` and a corresponding function that returns `true` only on
34 that exception. Although declared by syntactically identical
35 exception declarations, `e1` and `e2` are different exceptions. The
36 program, when run, prints `true`, `false`, `false`, `true`.
38 A slight modification of the above program shows that even a single
39 exception declaration yields a new exception each time it is
44 fun f (): exn * (exn -> bool) =
48 (E, fn E => true | _ => false)
52 fun pb (b: bool): unit =
53 print (concat [Bool.toString b, "\n"])
54 val () = (pb (isE1 e1)
60 Each call to `f` yields a new exception and a function that returns
61 `true` only on that exception. The program, when run, prints `true`,
62 `false`, `false`, `true`.
67 Exception generativity is required for type safety. Consider the
68 following valid SML program.
72 fun f (): ('a -> exn) * (exn -> 'a) =
76 (E, fn E x => x | _ => raise Fail "f")
78 fun cast (a: 'a): 'b =
80 val (make: 'a -> exn, _) = f ()
81 val (_, get: exn -> 'b) = f ()
85 val _ = ((cast 13): int -> int) 14
88 If exceptions weren't generative, then each call `f ()` would yield
89 the same exception constructor `E`. Then, our `cast` function could
90 use `make: 'a -> exn` to convert any value into an exception and then
91 `get: exn -> 'b` to convert that exception to a value of arbitrary
92 type. If `cast` worked, then we could cast an integer as a function
93 and apply. Of course, because of generative exceptions, this program
99 The `exn` type is effectively a <:UniversalType:universal type>.
104 * <:GenerativeDatatype:>