Ferrum.FSharp 0.4.1

dotnet add package Ferrum.FSharp --version 0.4.1
                    
NuGet\Install-Package Ferrum.FSharp -Version 0.4.1
                    
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.FSharp" Version="0.4.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ferrum.FSharp" Version="0.4.1" />
                    
Directory.Packages.props
<PackageReference Include="Ferrum.FSharp" />
                    
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.FSharp --version 0.4.1
                    
#r "nuget: Ferrum.FSharp, 0.4.1"
                    
#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.
#:package Ferrum.FSharp@0.4.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ferrum.FSharp&version=0.4.1
                    
Install as a Cake Addin
#tool nuget:?package=Ferrum.FSharp&version=0.4.1
                    
Install as a Cake Tool

Ferrum

  • Ferrum: Nuget

  • Ferrum.FSharp: Nuget

The F# + C# library for working with dynamic Error types.

Ferrum allows you to create errors based on the message, add context to errors, aggregate errors, and more. In many scenarios, using error-values can be more practical than using exceptions or errors as a simple string, which have awkward composition methods.

Open the Ferrum book to learn how to use Ferrum.

Quick start C# and F# examples

C# without Result<TValue, TError> monad type

using Ferrum;
using Ferrum.Errors;
using Ferrum.ExceptionInterop;
using Ferrum.Formatting;

public static class ReadmeExample
{
    public static IError? ReadFile(string path, out string content)
    {
        try
        {
            var text = File.ReadAllText(path);
            content = text;
            return null;
        }
        catch (Exception e)
        {
            content = string.Empty;
            return e.ToError();
        }
    }

    public static IError? CreateHello(out string hello)
    {
        var readError = ReadFile("name.txt", out var name);
        if (readError is not null)
        {
            hello = string.Empty;
            return new ContextError("Hello not created", readError);
        }

        hello = $"Hello, {name}!";
        return null;
    }

    public static void ItIsMain(string[] args)
    {
        var helloStringError = CreateHello(out var helloString);
        if (helloStringError is not null)
        {
            // Print:
            // I can't say hello: Hello not created: Could not find file '.../name.txt'.
            Console.WriteLine($"I can't say hello: {helloStringError.FormatS()}");
        }
        else
        {
            // Print:
            // I say: Hello, <name>!
            Console.WriteLine($"I say: {helloString}");
        }
    }
}

C# with dotNext

TODO

F#

open System.IO
open Ferrum
open Ferrum.FSharp

module ReadmeExample =

    let readFile (path: string) : Result<string, IError> =
        try
            Ok (File.ReadAllText(path))
        with ex ->
            Error (Error.ofException ex)

    let createHello () : Result<string, IError> =
        readFile "name.txt"
        |> Result.context "Hello not created"
        |> Result.map (fun name -> $"Hello, {name}!")

    let itIsMain (args: string array) : int =
        match createHello () with
        | Error error ->
            // Print:
            // I can't say hello: Hello not created: Could not find file '.../name.txt'.
            printfn $"I can't say hello: {Error.formatS error}"
        | Ok helloString ->
            // Print:
            // I say: Hello, <name>!
            printfn $"I say: {helloString}"
        0

When should use Ferrum?

The concept of a dynamic error is useful for non-domain code that doesn't care about the details of errors.

However, interfaces that add some structure allow for unified post-processing that doesn't rely on domain details.

Ferrum's interfaces are oriented toward (but not limited to) a chained error hierarchy, which is most useful for adding high-level context on top of low-level context.

Why not Exceptions?

In terms of basic properties, Ferrum.IError and System.Exception are equivalent. Message/Message, InnerError/InnerException, StackTrace/StackTrace. The difference is in the "emphasis". Errors are intended to be primarily transferable and composable values. These same properties are useful for TError in Result<TValue, TError> types.

It all comes down to stylistic preferences.

Result<TValue, TError> type

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

Library stability

In version 0.4, Ferrum is pretty experimental. Therefore, some components may be unstable. If we ignore the namespace and division into packages, then I would give the following stability rating:

The most stable components are IError, MessageError, ContextError, IErrorFormatter and related components.

Fairly stable components are IAggregateError, AggregateError, ITracedError, TracedMessageError, TracedContextError, TracedAggregateError, MessageErrorFormatter, SummaryErrorFormatter, DetailedErrorFormatter, DiagnosticErrorFormatter, ExceptionErrors, ErrorExceptions, AnyError.OfValue and related components.

The remaining components are the least stable.

Open an issue to discuss design elements, implementations, or use cases.

From v0.3 to v0.4 F# migration

Starting with v0.4, the core components were rewritten in C# so that non-F# .NET libraries could use Ferrum without unnecessary dependencies. The main Ferrum package became a C# package. To use F# integrations, use the Ferrum.FSharp package.

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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.4.1 42 8/2/2025
0.4.0 88 7/28/2025