MonadicSharp 1.3.3

dotnet add package MonadicSharp --version 1.3.3
                    
NuGet\Install-Package MonadicSharp -Version 1.3.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MonadicSharp" Version="1.3.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MonadicSharp" Version="1.3.3" />
                    
Directory.Packages.props
<PackageReference Include="MonadicSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MonadicSharp --version 1.3.3
                    
#r "nuget: MonadicSharp, 1.3.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=MonadicSharp&version=1.3.3
                    
Install as a Cake Addin
#tool nuget:?package=MonadicSharp&version=1.3.3
                    
Install as a Cake Tool

MonadicSharp 🚀

NuGet Version NuGet Downloads License: LGPL-3.0 GitHub NuGet .NET C#

🏆 Created by Danny4897 (aka Klexir on NuGet) | 📦 Available on NuGet.org

A professional-grade functional programming library for C# featuring Result<T>, Option<T>, Railway-Oriented Programming, and advanced monadic patterns. Build enterprise-ready applications with bulletproof error handling and sophisticated control flow.

✨ Key Features

  • 🚦 Result<T> - Advanced railway-oriented programming with comprehensive error handling
  • 🎯 Option<T> - Null-safe operations and robust optional value management
  • 🛡️ Try<T> - Sophisticated exception handling with retry mechanisms and circuit breakers
  • ⚖️ Either<TLeft, TRight> - Elegant dual-state modeling for complex scenarios
  • Ensure<T> - Contract-based validation with fluent assertion patterns
  • �🔄 Fluent Pipelines - Chain operations with elegant, readable syntax
  • Async Support - Complete async/await compatibility throughout
  • 🏗️ Type Safety - Leverage C#'s advanced type system for bulletproof code
  • 📦 Zero Dependencies - Lightweight, self-contained, and production-ready
  • 🔐 Enterprise Protection - Advanced intellectual property protection measures

🏛️ Professional Architecture

MonadicSharp follows a clean, modular architecture:

MonadicSharp/
├── Core/                    # Core monadic types
│   ├── Result.cs           # Railway-oriented programming
│   ├── Option.cs           # Null-safe operations  
│   ├── Try.cs              # Exception handling
│   ├── Either.cs           # Dual-state modeling
│   ├── Ensure.cs           # Contract validation
│   └── Unit.cs             # Functional unit type
├── Extensions/             # Extension methods
│   ├── FunctionalExtensions.cs
│   ├── PipelineExtensions.cs
│   └── DbSetExtensions.cs
└── Documentation/          # Comprehensive docs
    ├── ATTRIBUTION.md
    └── INTEGRITY.md

🚀 Quick Start

Installation

dotnet add package MonadicSharp

Essential Usage Patterns

🚦 Result<T> - Railway-Oriented Programming
using MonadicSharp.Core;
using MonadicSharp.Extensions;

// Chain operations with automatic error propagation
var result = Result.Success(42)
    .Map(x => x * 2)
    .Bind(x => x > 50 ? Result.Success(x) : Result.Failure("Value too small"))
    .Map(x => $"Final value: {x}");

result.Match(
    onSuccess: value => Console.WriteLine(value),
    onFailure: error => Console.WriteLine($"Error: {error}")
);
🎯 Option<T> - Null-Safe Operations
var safeResult = GetUser()
    .Map(u => u.Email)
    .Filter(email => email.Contains("@"))
    .GetValueOrDefault("no-email@example.com");
🛡️ Try<T> - Advanced Exception Handling
var robustOperation = Try.Execute(() => RiskyOperation())
    .ExecuteWithRetry(maxAttempts: 3, delayMs: 1000)
    .ExecuteWithCircuitBreaker(failureThreshold: 5, timeoutMs: 30000)
    .Match(
        onSuccess: result => $"Success: {result}",
        onFailure: ex => $"Failed after all attempts: {ex.Message}"
    );
⚖️ Either<TLeft, TRight> - Dual-State Modeling
Either<ValidationError, User> processUser = ValidateUser(userData)
    .Match(
        left: error => Either.Left<ValidationError, User>(error),
        right: validData => Either.Right<ValidationError, User>(CreateUser(validData))
    );
🔒 Ensure<T> - Contract Validation
var validatedUser = Ensure.That(user)
    .IsNotNull("User cannot be null")
    .Satisfies(u => u.Age >= 18, "User must be an adult")
    .Satisfies(u => !string.IsNullOrEmpty(u.Email), "Email is required")
    .Value; // Throws if any condition fails

🏗️ Project Templates

Get started quickly with MonadicSharp using our pre-built project templates:

Installation

# Install MonadicSharp templates
dotnet new install MonadicSharp.Templates

Available Templates

🚀 Monadic API (monadic-api)

A lightweight REST API template with functional programming patterns:

dotnet new monadic-api -n MyApi
cd MyApi
dotnet run
🏛️ Monadic Clean Architecture (monadic-clean)

A comprehensive Clean Architecture template with CQRS and functional patterns:

dotnet new monadic-clean -n MyApp
cd MyApp
dotnet run

Both templates include:

  • ✅ Complete MonadicSharp integration
  • ✅ Railway-Oriented Programming patterns
  • ✅ Result<T> error handling
  • ✅ Ready-to-run examples
  • ✅ Best practices implementation

📖 Learn more: Check the Templates README for detailed documentation

🔧 Core Types & Advanced Patterns

Result<T> - Railway-Oriented Programming

The foundation of error handling without exceptions:

// Success and failure creation
var success = Result.Success("Hello World");
var failure = Result.Failure<string>("Something went wrong");

// Advanced chaining with validation
var result = GetUser(id)
    .Bind(ValidateUser)
    .Bind(EnrichUserData)
    .Bind(SaveUser)
    .Map(u => new UserDto(u.Id, u.Name));

// Comprehensive error handling
result.Match(
    onSuccess: dto => ProcessSuccess(dto),
    onFailure: error => LogAndHandle(error)
);

Option<T> - Sophisticated Null Safety

Beyond simple null checks - comprehensive optional value handling:

// Safe value creation
var some = Option.Some(42);
var none = Option.None<int>();

// Complex transformation chains
var result = GetUser()
    .Map(u => u.Profile)
    .Bind(p => p.GetPreference("theme"))
    .Filter(theme => IsValidTheme(theme))
    .Map(theme => ApplyTheme(theme))
    .GetValueOrDefault(DefaultTheme);

Try<T> - Enterprise Exception Handling

Professional-grade exception management with advanced patterns:

// Basic exception handling
var result = Try.Execute(() => RiskyDatabaseOperation());

// Advanced retry with exponential backoff
var resilientResult = Try.Execute(() => CallExternalService())
    .ExecuteWithRetry(
        maxAttempts: 5, 
        delayMs: 1000, 
        backoffMultiplier: 2.0
    );

// Circuit breaker pattern
var protectedResult = Try.Execute(() => UnreliableService())
    .ExecuteWithCircuitBreaker(
        failureThreshold: 10,
        timeoutMs: 60000
    );

// Composite operations with contextual error handling
var complexResult = Try.ExecuteCompositeOperation(
    () => ValidateInput(),
    () => ProcessData(),
    () => SaveResults()
).ExecuteWithContextualErrorHandling("User registration process");

Either<TLeft, TRight> - Elegant Dual-State Modeling

Perfect for representing success/failure or valid/invalid states:

// Validation scenarios
Either<ValidationErrors, ValidUser> ValidateUser(UserInput input)
{
    var errors = new List<string>();
    
    if (string.IsNullOrEmpty(input.Email))
        errors.Add("Email required");
    
    if (input.Age < 18)
        errors.Add("Must be adult");
        
    return errors.Any() 
        ? Either.Left<ValidationErrors, ValidUser>(new ValidationErrors(errors))
        : Either.Right<ValidationErrors, ValidUser>(new ValidUser(input));
}

// Pattern matching
var processResult = ValidateUser(userInput)
    .Match(
        left: errors => HandleValidationErrors(errors),
        right: validUser => ProcessValidUser(validUser)
    );

Ensure<T> - Contract-Based Validation

Declarative validation with fluent syntax:

// Method parameter validation
public User CreateUser(string name, int age, string email)
{
    Ensure.That(name).IsNotNullOrEmpty("Name is required");
    Ensure.That(age).IsGreaterThan(0, "Age must be positive");
    Ensure.That(email).Satisfies(e => e.Contains("@"), "Invalid email format");
    
    return new User(name, age, email);
}

// Complex object validation
var validatedOrder = Ensure.That(order)
    .IsNotNull("Order cannot be null")
    .Satisfies(o => o.Items.Any(), "Order must have items")
    .Satisfies(o => o.Total > 0, "Order total must be positive")
    .Satisfies(o => o.Customer != null, "Order must have customer")
    .Value;

// Chaining validations
var processedUser = Ensure.That(user)
    .IsNotNull()
    .Satisfies(u => u.IsActive, "User must be active")
    .Transform(u => u.NormalizeEmail())
    .Satisfies(u => u.HasValidSubscription(), "Valid subscription required")
    .Value;

🔄 Advanced Pipeline Composition

Build sophisticated data processing pipelines with enterprise-grade error handling:

// Complex business logic pipeline
var userRegistrationPipeline = Pipeline
    .Start<UserRegistrationRequest>()
    .Then(ValidateUserInput)
    .Then(CheckUserUniqueness)
    .Then(HashPassword)
    .Then(CreateUserEntity)
    .Then(SaveUserToDatabase)
    .Then(SendWelcomeEmail)
    .Then(GenerateUserToken);

var result = await userRegistrationPipeline.ExecuteAsync(registrationRequest);

// Data transformation pipeline with error accumulation
var dataProcessingPipeline = Pipeline
    .Start<RawDataInput>()
    .Then(ValidateDataFormat)
    .Then(NormalizeData)
    .Then(EnrichWithMetadata)
    .Then(ApplyBusinessRules)
    .Then(TransformToOutputFormat)
    .ThenAsync(SaveToStorage);

// Parallel processing with error collection
var batchProcessingResult = await Pipeline
    .StartBatch(dataItems)
    .ProcessInParallel(item => ProcessSingleItem(item))
    .CollectResults()
    .HandleErrors(errors => LogBatchErrors(errors));

🎯 Enterprise Error Handling Patterns

Traditional Approach (Problematic ❌)

public User GetUser(int id)
{
    var user = database.Find(id);
    if (user == null) 
        throw new UserNotFoundException();
    
    if (!user.IsActive)
        throw new UserInactiveException();
        
    return user;
}

MonadicSharp Approach (Professional ✅)

public Result<User> GetUser(int id)
{
    return Ensure.That(id).IsGreaterThan(0, "Invalid user ID")
        .Transform(_ => database.Find(id))
        .ToResult("User not found")
        .Bind(ValidateUserActive)
        .Bind(EnrichUserData);
}

private Result<User> ValidateUserActive(User user)
{
    return user.IsActive 
        ? Result.Success(user)
        : Result.Failure("User account is deactivated");
}

private Result<User> EnrichUserData(User user)
{
    return Try.Execute(() => userService.LoadUserProfile(user))
        .ToResult("Failed to load user profile")
        .Map(profile => user.WithProfile(profile));
}

Advanced Error Handling with Context

public async Task<Result<ProcessingResult>> ProcessComplexWorkflow(WorkflowRequest request)
{
    return await Result.Success(request)
        .Bind(ValidateWorkflowRequest)
        .BindAsync(async req => await ExecuteWorkflowSteps(req))
        .Bind(ValidateWorkflowResults)
        .MapAsync(async results => await FinalizeWorkflow(results))
        .Match(
            onSuccess: result => 
            {
                logger.LogInformation("Workflow completed successfully: {WorkflowId}", result.Id);
                return Result.Success(result);
            },
            onFailure: error => 
            {
                logger.LogError("Workflow failed: {Error}", error);
                return Result.Failure<ProcessingResult>($"Workflow processing failed: {error}");
            }
        );
}

📖 Comprehensive API Reference

Result<T> Methods

  • Success<T>(T value) - Create a successful result
  • Failure<T>(string error) - Create a failed result
  • Map<TResult>(Func<T, TResult> func) - Transform the success value
  • Bind<TResult>(Func<T, Result<TResult>> func) - Chain operations with error propagation
  • Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure) - Pattern matching
  • Tap(Action<T> action) - Execute side effects without changing the result
  • TapError(Action<string> action) - Execute side effects on error
  • IsSuccess - Check if result is successful
  • IsFailure - Check if result has failed
  • Value - Get the success value (throws if failed)
  • Error - Get the error message (empty if successful)

Option<T> Methods

  • Some<T>(T value) - Create an option with value
  • None<T>() - Create an empty option
  • Map<TResult>(Func<T, TResult> func) - Transform the value if present
  • Bind<TResult>(Func<T, Option<TResult>> func) - Chain operations
  • Filter(Func<T, bool> predicate) - Filter based on condition
  • Match<TResult>(Func<T, TResult> onSome, Func<TResult> onNone) - Pattern matching
  • GetValueOrDefault(T defaultValue) - Get value or default
  • OrElse(Func<Option<T>> alternative) - Provide alternative option
  • HasValue - Check if option has a value
  • Value - Get the value (throws if empty)

Try<T> Methods

  • Execute<T>(Func<T> func) - Execute function with exception handling
  • ExecuteAsync<T>(Func<Task<T>> func) - Execute async function with exception handling
  • ExecuteWithRetry<T>(Func<T> func, int maxAttempts, int delayMs) - Execute with retry logic
  • ExecuteWithCircuitBreaker<T>(Func<T> func, int failureThreshold, int timeoutMs) - Execute with circuit breaker
  • ExecuteCompositeOperation<T>(params Func<T>[] operations) - Execute multiple operations as composite
  • Map<TResult>(Func<T, TResult> func) - Transform success value
  • Match<TResult>(Func<T, TResult> onSuccess, Func<Exception, TResult> onFailure) - Pattern matching

Either<TLeft, TRight> Methods

  • Left<TLeft, TRight>(TLeft left) - Create left-side either
  • Right<TLeft, TRight>(TRight right) - Create right-side either
  • Match<TResult>(Func<TLeft, TResult> onLeft, Func<TRight, TResult> onRight) - Pattern matching
  • MapLeft<TLeftResult>(Func<TLeft, TLeftResult> func) - Transform left value
  • MapRight<TRightResult>(Func<TRight, TRightResult> func) - Transform right value
  • IsLeft - Check if either is left-side
  • IsRight - Check if either is right-side

Ensure<T> Methods

  • That<T>(T value) - Start validation chain
  • IsNotNull(string message = null) - Ensure value is not null
  • IsNotNullOrEmpty(string message = null) - Ensure string is not null or empty
  • Satisfies(Func<T, bool> predicate, string message) - Custom validation
  • IsGreaterThan<TComparable>(TComparable threshold, string message) - Compare values
  • IsInRange<TComparable>(TComparable min, TComparable max, string message) - Range validation
  • Transform<TResult>(Func<T, TResult> transform) - Transform validated value
  • Value - Get the validated value (throws if validation failed)

Extension Methods

// Nullable conversions
string? nullable = GetNullableString();
var option = nullable.ToOption();
var result = option.ToResult("Value was null");

// Async operations  
var asyncResult = await GetUserAsync(id)
    .MapAsync(user => user.Email)  
    .BindAsync(ValidateEmailAsync)
    .TapAsync(email => LogEmailValidation(email));

// Collection operations
var results = await items
    .SelectAsync(ProcessItemAsync)
    .WhereSuccess()
    .CollectResults();

// Entity Framework integrations
var user = await dbContext.Users
    .FirstOrDefaultAsync(u => u.Id == id)
    .ToResult("User not found")
    .Bind(ValidateUserPermissions);

🏗️ Requirements & Compatibility

  • .NET 8.0 or later
  • C# 10.0 or later
  • Compatible with: ASP.NET Core, Entity Framework Core, Blazor, MAUI
  • Supports: Windows, Linux, macOS, Docker containers
  • Tested on: Azure, AWS, Google Cloud Platform

� Intellectual Property & Licensing

MonadicSharp is protected under LGPL-3.0-or-later license with comprehensive intellectual property safeguards:

✅ What You CAN Do:

  • ✅ Use MonadicSharp in commercial applications
  • ✅ Distribute applications that use MonadicSharp
  • ✅ Modify MonadicSharp for internal use
  • ✅ Create proprietary software that uses MonadicSharp as a library

❌ What You CANNOT Do:

  • ❌ Copy or redistribute MonadicSharp code without attribution
  • ❌ Create derivative works without sharing modifications under LGPL
  • ❌ Remove or modify copyright notices and license headers
  • ❌ Use MonadicSharp trademarks without permission

🛡️ Advanced Protection Features:

  • Digital Signatures: All releases are cryptographically signed
  • Integrity Verification: Built-in tampering detection mechanisms
  • Attribution Tracking: Embedded copyright and authorship information
  • License Compliance: Automated license validation and reporting

📋 Legal Note: This library includes sophisticated anti-piracy and intellectual property protection measures. Unauthorized copying, modification, or redistribution may result in legal action. For commercial licensing inquiries, please contact the author.

For complete licensing details, see LICENSE and Documentation/ATTRIBUTION.md.

📄 Documentation

🤝 Contributing & Support

We welcome contributions from the community! Here's how you can help:

🔧 Contributing Guidelines

  1. Fork the repository and create a feature branch
  2. Follow the existing code style and patterns
  3. Add tests for any new functionality
  4. Update documentation as needed
  5. Submit a pull request with clear description

🐛 Bug Reports

  • Use the GitHub issue tracker
  • Provide detailed reproduction steps
  • Include environment information (.NET version, OS, etc.)
  • Add relevant code samples

💡 Feature Requests

  • Describe the use case and benefit
  • Provide example API usage
  • Explain why it fits MonadicSharp's philosophy

📞 Support Channels

🎓 Learning Resources

📚 Functional Programming in C#

  • F# Core Library - Inspiration for functional patterns
  • Haskell - Source of monadic concepts
  • Rust's Result<T, E> - Error handling inspiration
  • Scala's Option[T] - Optional value handling

📖 Design Philosophy

MonadicSharp follows these core principles:

  • Explicit Error Handling - Make errors visible and manageable
  • Composability - Operations should chain naturally
  • Type Safety - Leverage the compiler to prevent runtime errors
  • Readability - Code should express intent clearly
  • Performance - Zero-cost abstractions where possible

🏆 About the Author

MonadicSharp is crafted with passion by Danny4897 (aka Klexir on NuGet).

🎯 Mission Statement

"To bring the elegance and safety of functional programming to the C# ecosystem, making robust error handling and null safety accessible to every .NET developer."

📈 Stats & Recognition

  • 🏅 Active NuGet Publisher with multiple successful packages
  • 🌟 Open Source Contributor to the .NET community
  • 🎓 Functional Programming Advocate and educator
  • 💼 Enterprise Software Developer with production experience

Made with ❤️ and lots of ☕ by Danny4897

"Write code that handles failure gracefully, and success will follow."

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.3 127 6/26/2025
1.3.0 281 6/12/2025
1.2.0 279 6/10/2025
1.1.0 247 6/9/2025
1.0.0 110 6/7/2025

v1.3.3: Minor release with improvements and bug fixes
v1.3.2: Enhanced IP protection with integrity verification, anti-tampering measures, and comprehensive copyright headers across all files
v1.3.1: Enhanced legal protection - Updated to LGPL-3.0 license for better IP protection while maintaining commercial usability
v1.3.0: Complete rebranding from FunctionalSharp to MonadicSharp - Templates, documentation, and package naming fully unified
v1.2.0: Changed namespace from FunctionalSharp to MonadicSharp to match NuGet package name
v1.1.0: Added Either<TLeft, TRight> type for representing two alternative types