Ferrum 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Ferrum --version 0.2.0
                    
NuGet\Install-Package Ferrum -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ferrum" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ferrum" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Ferrum" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ferrum --version 0.2.0
                    
#r "nuget: Ferrum, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Ferrum&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Ferrum&version=0.2.0
                    
Install as a Cake Tool

Ferrum

Nuget

The F# library for working with dynamic Error types.

The first library goal is providing lightweight general dynamic error type IError that can be used in Result error case (Result<'a, IError>) instead string or exn (Exception). The string error type does not compose well; exn is composable, but it is heavier and looks strange when not thrown. IError type is something in between.

The second library goal is providing contextual enrichment for errors.

Examples

IError usages

Ferrum provides 3 fundamental error types: message, context, wrap.

  • message is error that is created first and causes the all errors chain.
  • context is error that add context to other error.
  • wrap is error that wrap any 'e type to IError. It useful if impossible or too expensive to implement IError interface for 'e. 'e can be exception, but recommended use Error.ofException for converting exn -> IError.
let messageError: IError = Error.message "This is some error"
printfn $" > {messageError.FormatChain()}"
// > This is some error

let contextualError: IError = Error.context "Top error" (Error.message "Root error")
printfn $" > {contextualError.FormatChain()}"
// > Top error: Root error

type SomeError = SomeError
let wrappedError: IError = Error.wrap SomeError
printfn $" > {wrappedError.FormatChain()}"
// > SomeError

All operation are duplicated on Result module:

let messageResult: Result<unit, IError> = Result.message "This is some error"
printfn $" > {Utils.formatResultChain messageResult}"
// > Error (This is some error)

let contextualResult: Result<unit, IError> = Result.context "Top error" (Result.message "Root error")
printfn $" > {Utils.formatResultChain contextualResult}"
// > Error (Top error: Root error)

type SomeError = SomeError
let wrappedResult: Result<unit, IError> = Result.wrap (Error SomeError)
printfn $" > {Utils.formatResultChain wrappedResult}"
// > Error (SomeError)

Complex usage

[<RequireQualifiedAccess>]
type IOError =
    | FileNotFound

let readFile (_fileName: string) : Result<string, IOError> =
    Error IOError.FileNotFound

let makeGreeting () : Result<string, IError> =
    let readNameResult = readFile "name.txt" |> Result.wrap |> Result.context "Name is unknown"
    match readNameResult with
    | Error err -> Error err
    | Ok name -> Ok $"Hello, {name}"

let greet () : Result<unit, IError> =
    let makeGreetingResult = makeGreeting () |> Result.context "Greeting is not build"
    match makeGreetingResult with
    | Error err -> Error err
    | Ok greeting ->
        printfn $"{greeting}"
        Ok ()

let res: Result<unit, IError> = greet ()
printfn $" > {Utils.formatResultChain res}"
// > Error (Greeting is not build: Name is unknown: FileNotFound)

Custom IError implementation

type SimpleError =
    | SimpleCase
    with
        interface IError with
            member this.Reason =
                match this with
                | SimpleCase -> "Some simple error case"
            member this.Source =
                ValueNone

type ComplexError =
    | Source of SimpleError
    | SomeError
    with
        interface IError with
            member this.Reason =
                match this with
                | Source _ -> "Error caused by simple error source"
                | SomeError -> "Some complex error case"
            member this.Source =
                match this with
                | Source simpleError -> ValueSome simpleError
                | SomeError -> ValueNone

let simpleError = SimpleError.SimpleCase
printfn $" > {simpleError.Format(ErrorFormatters.ChainErrorFormatter.Instance)}"
// > Some simple error case

let complexErrorSomeError = ComplexError.SomeError
printfn $" > {complexErrorSomeError.Format(ErrorFormatters.ChainErrorFormatter.Instance)}"
// > Some complex error case

let complexErrorWithSource = ComplexError.Source SimpleError.SimpleCase
printfn $" > {complexErrorWithSource.Format(ErrorFormatters.ChainErrorFormatter.Instance)}"
// > Error caused by simple error source: Some simple error case

Why not Exceptions?

Exceptions have all the properties that IErrors have. Literally Reason ⇔ Message, Source ⇔ InnerException, StackTrace ⇔ StackTrace. The only difference is that IError is a bit more focused on using in Result and is possibly more lightweight. It is easy to implement a similar utilities for exn. It all comes down to stylistic preferences.

Additional Result and Error functions

At the moment, Ferrum has no goals to cover the usability of error handling beyond the universal error type. FsToolkit.ErrorHandling and other libraries do a great job with this.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Ferrum:

Package Downloads
Ferrum.Graphviz

Ferrum graphviz exporter

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 83 5/10/2025
0.2.0 165 3/30/2025
0.1.0 474 3/26/2025