Custom Errors in F#
open System
// A custom error type usually has the suffix "Error".
type ArgError(arg: int, message: string) =
inherit Exception(sprintf "%d - %s" arg message)
member this.Arg = arg
member this.Message = message
// Function that might return an error
let f arg =
if arg = 42 then
Error (ArgError(arg, "can't work with it"))
else
Ok (arg + 3)
// Main function
[<EntryPoint>]
let main _ =
// Pattern matching is used to handle the Result type
match f 42 with
| Ok result ->
printfn "Result: %d" result
| Error err when err :? ArgError ->
let argError = err :?> ArgError
printfn "%d" argError.Arg
printfn "%s" argError.Message
| Error _ ->
printfn "err doesn't match ArgError"
0
In F#, we can implement custom errors by creating a new type that inherits from the Exception
class. This is similar to implementing the Error()
method in the original example.
The f
function returns a Result
type, which is F#’s way of handling operations that might fail. It’s similar to returning a tuple of (int, error)
in the original code.
In the main
function, we use pattern matching to handle the Result
type. This is analogous to using errors.As
in the original code. The when
keyword in the pattern match allows us to check if the error is of type ArgError
.
To run this program:
$ dotnet fsi custom-errors.fsx
42
can't work with it
In F#, we typically use the dotnet fsi
command to run F# scripts directly, without needing to compile them first. This is similar to using go run
in Go.
F# provides a robust type system and pattern matching capabilities that make handling custom errors straightforward and type-safe.