Exceptions

In Fβ™―, thanks to Unions πŸ“, we can deal with expected errors using the Result type and optional union types for custom error - see πŸ”— Railway oriented programming.

Still, as exceptions are quite common in .NET, Fβ™― supports them fully and elegantly.

Type alias

Fβ™― provides the convenientexn alias for the System.Exception type.

Defining exceptions

To define our own exceptions, we can use the exception keyword:

// Without inner data
exception ArgumentNullOrWhiteSpaceException

// With inner data
exception MustBePositiveException of int

// With inner data with labels
exception ArgumentMustBePositiveException of name: string * value: int

☝️ Notes:

  • Naming convention: the exception name should end with Exception

  • Data labels are recommended for code clarity.

  • The syntax is close to a union type case for the exception's definition and its handling with pattern matching - see Full example below.

  • We can also define exceptions by inheriting from System.Exception. This is the Cβ™― style, but it is not recommended because it's less elegant for both definition and handling.

Throwing exceptions

Fβ™― provides a set of convenient helpers:

  • raise (exn: exn)

    • throw a custom exception object

    • equivalent of throw exn; in Cβ™―

  • reraise ()

    • used in a (try...) with block to propagate a handled exception up the call chain

    • equivalent of throw; in Cβ™―

    • preserve the stack trace, contrary to raise ex

    • to do the same outside of a (try...) with block, it's more complicated β†’ πŸ”— https://stackoverflow.com/a/41202215/8634147

  • failwith (message: string) and failwithf (messageTemplate: string) (...args)

    • generate a general Fβ™― exception with the given message

    • failwith is the shortcut for raise (Exception message)

    • failwithf is less used since Fβ™― supports string interpolation.

  • invalidArg (argumentName: string) (message: string)

    • generate a System.ArgumentException for the given argument name and with the specified message

    • shortcut for raise (ArgumentException(message, argumentName))

  • nullArg (argumentName: string)

    • generate a System.NullArgumentException for the given argument name

    • shortcut for raise (ArgumentNullException argumentName)

  • invalidOp (message: string)

    • generate a System.InvalidOperationException with the given message

    • shortcut for raise (InvalidOperationException message)

Examples:

Handling exceptions

β†’ try/with expression

☝️ Notes:

  • The keyword used is with, not catch, contrary to Cβ™―.

  • There is no try/with/finally expression, only try/finally that we can nest in another try/with.

  • The with block is using pattern matching:

    • :? ExceptionType to check if the handled exception has or derives from the given type.

    • Failure message is an active pattern to catch low-level exceptions that have exactly theSystem.Exception type. β†’ useful to handle exceptions raised by failwith(f) helpers.

    • Exceptions defined using the exception keyword can be deconstructed β†’ see Full example below.

Full example

The following example demonstrates almost every topic we studied:

  • How to define an exception type

  • How to raise an exception using different helpers

  • How to catch the exception and pattern match it

Outputs

Pattern order

Deconstruction patterns

Last updated

Was this helpful?