-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
There are some common patterns for managing exceptions that are syntactic features of many programming languages. Implementing them is possible in Standard ML, but usually requires code duplication. That is why I recommend the following additions to the Fn
module:
signature FN = sig
(* Run the function, returning the exception as a value if execution raised an exception *)
val try : (unit -> 'a) -> (exn, 'a) Either.either
(* Run the second thunk after the first, even if an exception was raised *)
val finally : (unit -> 'a) -> (unit -> unit) -> 'a
(* Use the provided init and deinit functions to manage the resource 'r,
making sure to run the deinit function even if an exception is raised.
Notably: an exception raised in the deinit function will be raised *)
val bracket : {init : unit -> 'r, deinit : 'r -> unit} -> ('r -> 'a) -> 'a
end
Implementation
fun try th = Either.INR (th ()) handle e => Either.INL e
fun finally f1 f2 = let
val r = f1 () handle e => (f2 (); raise e)
in f2 (); r end
fun bracket {init, deinit} f = let
val x = init ()
val r = f x handle e => (deinit x; raise e)
in deinit x; r end
HarrisonGrodinHarrisonGrodin
Metadata
Metadata
Assignees
Labels
No labels