Skip to content

shahabganji/Funx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Funx

Build status codecov

This is an functional library for C# developers, all the features are implemented based on what Enrico taught in his Functional Programming in C#. I tried to learn them and write one for myself.

Introduction

Funx provides robust and well-tested core basic structs for functional programming in C#, Option and Either. Option represents a possibility of lack of value.

Installation

Easily install it via Nuget.

Install-Package Funx

dotnet add package Funx

Usage

Option

using Funx;
// using static Funx.Helpers; // in some scenarios it may provide better syntax && readability

var none = Option<string>.None; // or Option<string> none = None;
var author = Option<string>.Some("Enrico");

var value = author.Match(() => "No Name", v => v);
WriteLine(value); // Enrico

value = none.Match(() => "No Name", v => v);
WriteLine(value); //  No Name

I would rather to use it in a different way, since all native types can be implicitly cast to Option

using Funx;
using static Funx.Factories;

Option<string> none = None;
Option<string> author = "Enrico";

var value = author.Match(() => "No Name", v => v);
WriteLine(value); // Enrico

value = none.Match(() => "No Name", v => v);
WriteLine(value); //  No Name

Should you require more functionality and methods, import Funx.Extensions namespace and you'll get a bunch of handy extension method.

using Funx;
using Funx.Extensions;

var student = new Author { Name = "Jane", Age = 17 };

var isTeenager = student.Where( s => s.Age < 20 && s.Age > 13 );

// ***** OR *********

var isTeenager = from s in student
                 where s.Age > 13 && s.Age < 20
                 select s;

If you want to induce side effects use ForEach method, the provided function will be called if a value exists:

Option<int> option = 11;

option.ForEach(WriteLine);

To map Option to another option use Map, and Bind functions, the Map accepts a function which returns TR, and Bind accepts a function which returns Option<TR>, if we pass the latter function to Map will end up with nested Options, like <Option<Option<TR>>>, which might not be what we expect:

using Funx.Extensions;
using static Funx.Factories;

var str = Some("value");

string ToUpper(string v) => v.ToUpper();

var upperCase = str.Map(ToUpper); // upperCase is an Option<string> too.
using Funx;
using Funx.Extensions;
using static Funx.Factories;

var str = Some("value");

string ToUpper(string v) => v.ToUpper();

Option<string> IsValid(string v)
{
    if (v.StartsWith("v"))
        return v; // all types can implicitly cast to Option<T>, so simply return them.

    return None;
}

var upperCase = str.Bind(IsValid).Map(ToUpper); // here upperCase is Option<string>, but if we've used Map function it would be Option<Option<string>>

upperCase.ForEach(WriteLine);