Custom Errors in Standard ML
(* A custom error type usually has the suffix "Error". *)
datatype argError = ArgError of {arg: int, message: string}
(* Adding this toString function makes argError printable *)
fun toString (ArgError {arg, message}) =
Int.toString arg ^ " - " ^ message
(* Function that might return an error *)
fun f arg =
if arg = 42 then
NONE
else
SOME (arg + 3)
(* Main function *)
fun main () =
case f 42 of
NONE =>
let
val err = ArgError {arg = 42, message = "can't work with it"}
in
print (Int.toString (#arg (case err of ArgError r => r)) ^ "\n");
print (#message (case err of ArgError r => r) ^ "\n")
end
| SOME result =>
print ("Result: " ^ Int.toString result ^ "\n")
(* Run the main function *)
val _ = main ()
In Standard ML, we don’t have a built-in error type like in some other languages. Instead, we use the Option
type to represent potential failures. Here’s how the code works:
We define a custom
argError
datatype to represent our error condition. It contains anarg
(integer) and amessage
(string).We create a
toString
function for ourargError
type to make it easily printable.The
f
function returnsNONE
when the input is 42 (simulating an error condition), andSOME (arg + 3)
otherwise.In the
main
function, we callf 42
and pattern match on the result:- If it’s
NONE
, we create anargError
and print its components. - If it’s
SOME result
, we print the result.
- If it’s
Finally, we call the
main
function to execute our program.
To run this program:
- Save it to a file, e.g.,
custom_errors.sml
. - Use an SML interpreter or compiler to run it. For example, with Standard ML of New Jersey (SML/NJ):
$ sml custom_errors.sml
42
can't work with it
This example demonstrates how to create and use custom error types in Standard ML, even though the language doesn’t have a built-in error handling mechanism like some other languages. Instead, it uses algebraic data types and pattern matching to achieve similar functionality.