A modern functional programming library for C# featuring Result<T>, Option<T>, Railway-Oriented Programming, and fluent pipeline composition. Build robust applications with elegant error handling and monadic patterns.
$ dotnet add package MonadicSharpA modern functional programming library for C# featuring Result, Option, Railway-Oriented Programming, and fluent pipeline composition. Build robust applications with elegant error handling and monadic patterns.
dotnet add package MonadicSharp
using MonadicSharp;
using MonadicSharp.Extensions;
// Result<T> for error handling
var result = Result.Success(42)
.Map(x => x * 2)
.Bind(x => x > 50 ? Result.Success(x) : Result.Failure("Too small"))
.Map(x => $"Final value: {x}");
result.Match(
onSuccess: value => Console.WriteLine(value),
onFailure: error => Console.WriteLine($"Error: {error}")
);
// Option<T> for null-safe operations
var user = GetUser()
.Map(u => u.Email)
.Filter(email => email.Contains("@"))
.GetValueOrDefault("no-email@example.com");
Railway-oriented programming for elegant error handling:
// Success path
var success = Result.Success("Hello World");
// Failure path
var failure = Result.Failure<string>("Something went wrong");
// Chaining operations
var result = GetUser(id)
.Bind(ValidateUser)
.Bind(SaveUser)
.Map(u => u.Id);Null-safe operations without null reference exceptions:
// Some value
var some = Option.Some(42);
// No value
var none = Option.None<int>();
// Safe operations
var result = GetUser()
.Map(u => u.Name)
.Filter(name => name.Length > 0)
.GetValueOrDefault("Anonymous");Build complex data processing pipelines:
var pipeline = Pipeline
.Start<string>()
.Then(ParseNumber)
.Then(ValidateRange)
.Then(FormatOutput);
var result = await pipeline.ExecuteAsync("42");public User GetUser(int id)
{
var user = database.Find(id);
if (user == null)
throw new UserNotFoundException();
if (!user.IsActive)
throw new UserInactiveException();
return user;
}public Result<User> GetUser(int id)
{
return database.Find(id)
.ToResult("User not found")
.Bind(ValidateUserActive);
}
private Result<User> ValidateUserActive(User user)
{
return user.IsActive
? Result.Success(user)
: Result.Failure("User is inactive");
}Success<T>(T value) - Create a successful resultFailure<T>(string error) - Create a failed resultMap<TResult>(Func<T, TResult> func) - Transform the success valueBind<TResult>(Func<T, Result<TResult>> func) - Chain operationsMatch<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure) - Pattern matchIsSuccess - Check if result is successfulIsFailure - Check if result has failedValue - Get the success value (throws if failed)Error - Get the error message (empty if successful)Some<T>(T value) - Create an option with valueNone<T>() - Create an empty optionMap<TResult>(Func<T, TResult> func) - Transform the value if presentBind<TResult>(Func<T, Option<TResult>> func) - Chain operationsFilter(Func<T, bool> predicate) - Filter based on conditionMatch<TResult>(Func<T, TResult> onSome, Func<TResult> onNone) - Pattern matchGetValueOrDefault(T defaultValue) - Get value or defaultHasValue - Check if option has a valueValue - Get the value (throws if empty)// Convert nullable to Option
string? nullable = GetNullableString();
var option = nullable.ToOption();
// Convert to Result
var result = option.ToResult("Value was null");
// Async operations
var asyncResult = await GetUserAsync(id)
.MapAsync(user => user.Email)
.BindAsync(ValidateEmailAsync);This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
Made with ❤️ by Danny4897