ApacheTech.Common.FunctionalCSharp
1.1.0
dotnet add package ApacheTech.Common.FunctionalCSharp --version 1.1.0
NuGet\Install-Package ApacheTech.Common.FunctionalCSharp -Version 1.1.0
<PackageReference Include="ApacheTech.Common.FunctionalCSharp" Version="1.1.0" />
<PackageVersion Include="ApacheTech.Common.FunctionalCSharp" Version="1.1.0" />
<PackageReference Include="ApacheTech.Common.FunctionalCSharp" />
paket add ApacheTech.Common.FunctionalCSharp --version 1.1.0
#r "nuget: ApacheTech.Common.FunctionalCSharp, 1.1.0"
#:package ApacheTech.Common.FunctionalCSharp@1.1.0
#addin nuget:?package=ApacheTech.Common.FunctionalCSharp&version=1.1.0
#tool nuget:?package=ApacheTech.Common.FunctionalCSharp&version=1.1.0
Functional C# - End-Game LINQ Library
A comprehensive C# library that brings practical functional programming tools to everyday .NET development. It provides monads, discriminated unions, memoisation helpers, currying and partial application utilities, and a small set of LINQ-style extensions to make common functional patterns concise and expressive.
Support the Author
If you find this library useful and would like to support its continued development, please consider one of the options below. Your support helps fund maintenance, documentation and new features.
- Join my Patreon
- Donate via PayPal
- Buy Me a Coffee
- Subscribe on Twitch
- Subscribe on YouTube
- Purchase from my Amazon Wishlist
- Visit my website
Installation
Install the package from NuGet:
dotnet add package ApacheTech.Common.FunctionalCSharp
Alternatively, add the ApacheTech.Common.FunctionalCSharp
project to your solution and reference it directly during development.
Key Concepts
This section summarises the principal APIs and how they are intended to be used.
Monads
Monads in this library are pragmatic tools for modelling optional values and fallible computations.
Maybe<T>
represents an optional value. UseActual<T>
for present values andNothing<T>
for absence. Companion extensions such asToMaybe()
andBind()
make chaining straightforward and safe.Identity<T>
is a minimal wrapper that carries a value and supports implicit conversions. It is useful when a monadic interface is desired without special semantics for missing values.Attempt<T>
models computations that may fail.Success<T>
contains the result;Fail<T>
contains an exception and short-circuits subsequent operations.
Usage guidance: prefer Maybe
where absence is a valid state and Attempt
where exceptions should be modelled explicitly in the computation chain.
OneOf � discriminated unions
OneOf<T1, T2>
holds one of two possible types. Use Match
or Invoke
to handle each case explicitly. This pattern is useful when a function may return one of a small set of distinct types (for example, a result or an error value) and you want callers to handle both cases explicitly.
Memento (memoisation)
Memento<TInput, TOutput>
decorates a pure function with a dictionary-backed cache. It offers implicit conversions to and from Func<TInput, TOutput>
to ease substitution of decorated and plain functions.
Important caveats: use only for pure, deterministic functions, and ensure TInput
is a suitable dictionary key (immutable or with stable equality semantics).
Functional helpers (Apply & Curry)
Apply
(partial application) binds leading arguments of a function to produce a function of smaller arity, which can be useful for creating specialised functions.Curry
converts a multi-argument function into nested single-argument functions, facilitating composition and reuse in functional pipelines.
Both families include overloads for a broad range of arities.
Monadic LINQ-style helpers
Map
applies a transformation to a value and returns the result.Alt
attempts a primary mapping and uses a fallback when the primary result is a default value.Fork
executes multiple independent paths against the same input and combines the results using a provided join function.TryValidate
returns whether all predicates hold and provides the set of failing rules;Validate
simply returns a boolean.
These helpers aim to make common patterns succinct and readable.
Try/catch helpers & object utilities
A small set of helpers reduces boilerplate around common error handling patterns. TryCatch<TException>
wraps an Action
with a handler for the specified exception type; convenience variants include TryOrFailFast
, TryOrThrow
, TryOrLogToConsole
and TryOrLogToDebug
.
IsDefaultValue<T>
tests whether a value equals the default for its type and is useful for concise default checks.
Examples / Recipes
This section contains compact examples illustrating typical usage patterns.
Chaining fallible computations
Parse, transform and format only when each step succeeds. The chain short-circuits on failure.
using ApacheTech.Common.FunctionalCSharp.Monads;
using ApacheTech.Common.FunctionalCSharp.Monads.Extensions;
var formatted = "123"
.ToMaybe()
.Bind(i => (i * 2).ToMaybe())
.Map(i => i.ToString());
Handling multiple result types with OneOf
Use OneOf
to return one of two types and handle both cases explicitly.
var result = new OneOf<int, string>(404);
string message = result.Match(
code => $"Error code: {code}",
text => $"Message: {text}"
);
Memoising an expensive pure function
Decorate a pure function with Memento
to cache results for repeated inputs.
Func<string, string> computeKey = s => s.ToUpperInvariant(); // expensive
var memoKey = new Memento<string, string>(computeKey);
var k1 = memoKey.Invoke("abc"); // computed
var k2 = memoKey.Invoke("abc"); // cached
Validation helpers
Run multiple predicates and inspect failures.
var user = new User { Name = "", Age = 12 };
var ok = user.TryValidate(out var failed,
u => !string.IsNullOrWhiteSpace(u.Name),
u => u.Age >= 13);
if (!ok)
{
foreach (var rule in failed) Console.WriteLine("Validation failed");
}
Contributing
Contributions, bug reports and improvements are welcome. Please open issues or pull requests against the GitHub repository. When contributing, please follow the existing code style and add unit tests for new behaviours.
- Run
dotnet test
in the test project before submitting changes.
Licence
This project is released under the terms of the licence included in LICENCE.md
.
Product | Versions 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. |
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ApacheTech.Common.FunctionalCSharp:
Package | Downloads |
---|---|
VintageStory.Gantry
Gantry MDK is a Mod Developent Kit, used to create third-party plugins for the game Vintage Story, by Anego Studios. |
GitHub repositories
This package is not used by any popular GitHub repositories.
ApacheTech.Common.FunctionalCSharp v1.1.0
Build: Updated to .NET 8.0 SDK.