https://github.com/polyadic/funcky-discriminated-union
A source generator that generates Match methods for all your discriminated unions needs. ✨
https://github.com/polyadic/funcky-discriminated-union
Last synced: 21 days ago
JSON representation
A source generator that generates Match methods for all your discriminated unions needs. ✨
- Host: GitHub
- URL: https://github.com/polyadic/funcky-discriminated-union
- Owner: polyadic
- License: other
- Created: 2021-11-19T22:49:03.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-02-04T10:19:33.000Z (3 months ago)
- Last Synced: 2025-04-04T23:48:40.225Z (about 1 month ago)
- Language: C#
- Homepage:
- Size: 144 KB
- Stars: 7
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: readme.md
- Changelog: changelog.md
- License: license-apache.txt
Awesome Lists containing this project
- RSCG_Examples - https://github.com/polyadic/funcky-discriminated-union
- csharp-source-generators - Funcky Discriminated Unions -   A source generator that generates `Match` methods for all your discriminated unions needs. ✨ Can be used with or without the functional programming library Funcky. (Source Generators / Functional Programming)
README
# Funcky Discriminated Unions
A source generator that generates `Match` methods for all your discriminated unions needs. ✨[](https://www.nuget.org/packages/Funcky.DiscriminatedUnion)
[](https://github.com/polyadic/funcky-discriminated-union/actions?query=workflow%3ABuild)
[](https://raw.githubusercontent.com/polyadic/funcky-discriminated-union/main/license-mit.txt)
[](https://raw.githubusercontent.com/polyadic/funcky-discriminated-union/main/license-apache.txt)## Installation
Add `` to your project file.## Usage
Apply the `[DiscriminatedUnion]` to an abstract class (or record) with nested types representing the variants.## Example
```cs
using Funcky;var result = Result.Ok(42);
var resultOrFallback = result.Match(ok: ok => ok.Value, error: _ => 0);[DiscriminatedUnion]
public abstract partial record Result
where T : notnull
{
public sealed partial record Ok(T Value) : Result;public sealed partial record Error(Exception Exception) : Result;
}
```## 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.```cs
using Funcky;[DiscriminatedUnion(MatchResultTypeName = "TMatchResult")]
public abstract partial record Result { ... }// Generated code
partial record Result
{
public abstract TMatchResult Match(...);...
}
```### `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.```cs
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][json-polymorphism-docs] 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.```cs
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
```cs
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` of your type.```cs
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
```cs
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);
```[json-polymorphism-docs]: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism