Funcky.DiscriminatedUnion 1.2.0

dotnet add package Funcky.DiscriminatedUnion --version 1.2.0                
NuGet\Install-Package Funcky.DiscriminatedUnion -Version 1.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="Funcky.DiscriminatedUnion" Version="1.2.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Funcky.DiscriminatedUnion --version 1.2.0                
#r "nuget: Funcky.DiscriminatedUnion, 1.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.
// Install Funcky.DiscriminatedUnion as a Cake Addin
#addin nuget:?package=Funcky.DiscriminatedUnion&version=1.2.0

// Install Funcky.DiscriminatedUnion as a Cake Tool
#tool nuget:?package=Funcky.DiscriminatedUnion&version=1.2.0                

Funcky Discriminated Unions

A source generator that generates Match methods for all your discriminated unions needs. ✨

NuGet package Build Licence: MIT Licence: Apache

Installation

Add <ProjectReference Include="Funcky.DiscriminatedUnion" Version="..." PrivateAssets="all" /> to your project file.

Usage

Apply the [DiscriminatedUnion] to an abstract class (or record) with nested types representing the variants.

Example

using Funcky;

var result = Result<int>.Ok(42);
var resultOrFallback = result.Match(ok: ok => ok.Value, error: _ => 0);

[DiscriminatedUnion]
public abstract partial record Result<T>
    where T : notnull
{
    public sealed partial record Ok(T Value) : Result<T>;

    public sealed partial record Error(Exception Exception) : Result<T>;
}

Minimum Required Versions

  • Visual Studio 2022
  • Roslyn 4.0.0
  • .NET 6

Settings

The attribute allows configuration of some aspects of source generation.

NonExhaustive

The auto-generated Match and Switch methods are public by default. When NonExhaustive is set to true, these methods are generated with internal visibility instead.

MatchResultTypeName

The auto-generated Match method uses a generic type for the result. This type is named TResult by default. This can cause conflict with generic types on the discriminated union itself. Use MatchResultTypeName to set a custom name for this type.

using Funcky;

[DiscriminatedUnion(MatchResultTypeName = "TMatchResult")]
public abstract partial record Result<TResult> { ... }

// Generated code
partial record Result<TResult>
{
    public abstract TMatchResult Match<TMatchResult>(...);

    ...
}

Flatten

The auto-generated Match and Switch methods only accept one level of inheritance by default. Set Flatten to true to include arbitrarily deep inherited types in these methods.

using Funcky;

SyntaxNode node = ...;
var nodeAsString = node.Match(
    keyword: keyword => keyword.Value,
    integer: integer => integer.Value.ToString(),
    double: @double => @double.Value.ToString());

[DiscriminatedUnion(Flatten = true)]
public abstract partial record SyntaxNode
{
    public sealed partial record Keyword(string Value) : SyntaxNode;

    public abstract partial record Literal : SyntaxNode;

    public abstract partial record Number : Literal;

    public sealed partial record Integer(int Value) : Number;

    public sealed partial record Double(double Value) : Number;
}

[JsonPolymorphic]

System.Text.Json adds support for serializing derived classes starting with .NET 7. This generator supports this feature by generating the required [JsonDerivedType] attributes for you.

All missing [JsonDerivedType] attributes are generated if at least one [JsonDerivedType] or [JsonPolymorphic] attribute is specified.

using Funcky;
using System.Text.Serialization;

[DiscriminatedUnion]
[JsonPolymorphic]
public abstract partial record Shape
{
    public sealed partial record Rectangle(double Width, double Length) : Shape;

    public sealed partial record Circle(double Radius) : Shape;

    public sealed partial record EquilateralTriangle(double SideLength) : Shape;
}

<details>

<summary>Generated code</summary>

using System.Text.Serialization;

[JsonDerivedType(typeof(Rectangle), typeDiscriminator: nameof(Rectangle))]
[JsonDerivedType(typeof(Circle), typeDiscriminator: nameof(Circle))]
[JsonDerivedType(typeof(EquilateralTriangle), typeDiscriminator: nameof(EquilateralTriangle))]
partial record Shape
{
    // ...
}

</details>

GeneratePartitionExtension

Set GeneratePartitionExtension to true to auto-generate partition methods for IEnumerable<T> of your type.

using Funcky;
using System.Text.Serialization;

[DiscriminatedUnion(GeneratePartitionExtension = true)]
public abstract partial record Result
{
    public sealed partial record Ok() : Result;

    public sealed partial record Warning(string Message) : Result;

    public sealed partial record Error(string Message) : Result;
}

<details>

<summary>Usage</summary>

var results = new Result[] { new Result.Ok(), /* ... */ }

// N-Tuple extension method:
var (oks, warnings, errors) = results.Partition();

// Extension method with result selector:
var warningAndErrorCount = results.Partition(resultSelector: (_, warnings, errors) => warnings.Count + errors.Count);

</details>

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

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
1.2.0 114 10/1/2024
1.1.0 4,251 11/22/2022
1.0.0 3,576 9/14/2022
0.1.0 1,624 11/22/2021