RSCG – Funcky.DiscriminatedUnion

RSCG – Funcky.DiscriminatedUnion
 
 

name Funcky.DiscriminatedUnion
nuget https://www.nuget.org/packages/Funcky.DiscriminatedUnion/
link https://github.com/polyadic/funcky-discriminated-union
author Polyadic

Generating discriminated unions for C# 9.0 and above.

 

This is how you can use Funcky.DiscriminatedUnion .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Funcky.DiscriminatedUnion" Version="1.1.0"  />
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using Union;

Console.WriteLine("Save or not");
var data = SaveToDatabase.Save(0);

Console.WriteLine(data.Match(ok => true, error => false));
data = SaveToDatabase.Save(1);
Console.WriteLine(data.Match(ok => true, error => false));



namespace Union;

[Funcky.DiscriminatedUnion]
public abstract partial record ResultSave
{
    public partial record Success(int Value): ResultSave;
    public partial record ValidationError(string Message):ResultSave;

    //public sealed partial record Ok(T Value) : ResultSave<T>;

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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Union;
internal class SaveToDatabase
{
    public static ResultSave Save(int i)
    {
        if (i == 0)
        {
            return new ResultSave.ValidationError(" cannot save 0");
        }
        return new ResultSave.Success(i);
    }
}


 

The code that is generated is

// <auto-generated/>
#nullable enable

namespace Funcky
{
    [global::System.Diagnostics.Conditional("Funcky_DiscriminatedUnion")]
    [global::System.AttributeUsage(global::System.AttributeTargets.Class)]
    internal sealed class DiscriminatedUnionAttribute : global::System.Attribute
    {
        /// <summary>Allow only consumers in the same assembly to use the exhaustive <c>Match</c> and <c>Switch</c> methods.</summary>
        public bool NonExhaustive { get; set; }

        /// <summary>Generates exhaustive <c>Match</c> and <c>Switch</c> methods for the entire type hierarchy.</summary>
        public bool Flatten { get; set; }

        /// <summary>Customized the generic type name used for the result in the generated <c>Match</c> methods. Defaults to <c>TResult</c>.</summary>
        public string? MatchResultTypeName { get; set; }
    }
}

// <auto-generated/>
#nullable enable

namespace Union
{
    partial record ResultSave
    {
        [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
        public abstract TResult Match<TResult>(global::System.Func<Success, TResult> success, global::System.Func<ValidationError, TResult> validationError);
        
        [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
        public abstract void Switch(global::System.Action<Success> success, global::System.Action<ValidationError> validationError);
        
        partial record Success
        {
            [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
            public override TResult Match<TResult>(global::System.Func<Success, TResult> success, global::System.Func<ValidationError, TResult> validationError) => success(this);
            
            [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
            public override void Switch(global::System.Action<Success> success, global::System.Action<ValidationError> validationError) => success(this);
        }
        
        partial record ValidationError
        {
            [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
            public override TResult Match<TResult>(global::System.Func<Success, TResult> success, global::System.Func<ValidationError, TResult> validationError) => validationError(this);
            
            [global::System.CodeDom.Compiler.GeneratedCode("Funcky.DiscriminatedUnion.SourceGeneration", "1.1.0.0")]
            public override void Switch(global::System.Action<Success> success, global::System.Action<ValidationError> validationError) => validationError(this);
        }
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Funcky.DiscriminatedUnion