Skip to content

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

License

Unknown and 2 other licenses found

Licenses found

Unknown
license.txt
Apache-2.0
license-apache.txt
MIT
license-mit.txt
Notifications You must be signed in to change notification settings

polyadic/funcky-discriminated-union

Funcky Discriminated Unions

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

NuGet Version Build Licence: MIT Licence: Apache

Installation

Add <PackageReference 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;
}
Generated code
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
{
    // ...
}

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;
}
Usage
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);

About

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

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
license.txt
Apache-2.0
license-apache.txt
MIT
license-mit.txt

Stars

Watchers

Forks

Contributors 5

Languages

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy