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"
0In 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 itIn 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.