LanguageExt is a functional language extension library for C#. It was created by Paul Louth and aims to facilitate working with functional features in C#, such as functional programming, immutability.
LanguageExt is based on best practices in functional programming and provides a wide range of data structures and functions to help developers write cleaner, more concise, and safer code.
LanguageExt provides a wide range of functional features for C#, including:
- Immutable data structures, such as lists and maps.
- Higher-order functions, such as map and fold.
- Asynchronous programming with support for cancellation and exceptions.
- Option and result types to avoid runtime exceptions.
- A concurrency system based on agents and channels.
This library is not small. On the contrary, it is a huge library, which provides a large number of tools that represent a significant change in the way C# is used.
However, it is not necessary to use all the tools all the time. LanguageExt is presented as a collection of utilities that are beneficial to use on some occasions.
On the other hand, many of the features offered by LanguageExt have been gradually incorporated into .NET versions, which continue their own evolution towards more functional paradigms.
Personally, I also see this library as a “testing ground” for new possibilities and trends in software development, as well as providing certain practical utilities that do have an immediate use.
How to use Language-ext
We can easily add the library to a .NET project, through the corresponding Nuget package.
Install-Package LanguageExt.Core
Here are some examples of using Language-ext extracted from the library’s documentation
Null
We can easily handle Null objects thanks to Option<T>
var optional = Some(123);
int x = optional
.Some( v => v * 2 )
.None( () => 0 );
int x = optional.IfNone(10);
Matching
Using Option<T>
along with matching.
Option<int> two = Some(2);
Option<int> four = Some(4);
Option<int> six = Some(6);
Option<int> none = None;
int r = match( from x in two
from y in four
from z in six
select x + y + z,
Some: v => v * 2,
None: () => 0 ); // r == 24
Out Parameters
Avoid using Out parameters through Option<T>
int res = parseInt("123").IfNone(0);
int res = parseInt("123").Match(
Some: x => x * 2,
None: () => 0
);
Unit
Unit data type to avoid using void to indicate absence of type.
public static Func<string, Unit> GetConsoleWrite() => fun<string>(Console.Write);
public static Func<string, Task<Unit>> GetConsoleWriteAsync() => (string v) => Console.Out.WriteAsync(v).ToUnit();
public static Unit WriteToConsole(string v) => fun(() => Console.Write(v))();
public static Task<Unit> WriteToConsoleAsync(string v) => Console.Out.WriteAsync(v).ToUnit();
Collections
It also offers immutable collections, such as lists and maps
var test = List(1, 2, 3, 4, 5);
var list = Range(500,1000);
var res = List(1, 2, 3, 4, 5)
.Map(x => x * 10)
.Filter(x => x > 20)
.Fold(0, (x, s) => s + x);
Or, for example, immutable dictionaries
var dict = Map<string,int>();
var people = Map((1, "Rod"),
(2, "Jane"),
(3, "Freddy"));
Option<string> result = find(people, 1);
var res = match( find(people, 100),
Some: v => "Hello " + v,
None: () => "failed" );
Functions
Definition of functions under a more functional paradigm
public int Sum(IEnumerable<int> list) => match( list,
() => 0,
(x, xs) => x + Sum(xs)
);
These are just examples of some of the features. But the library offers many, many (many!) Check out the documentation because it’s really interesting, even if it’s just as a source of inspiration and ideas.
Language-ext is Open Source, and all the code and documentation is available in the project’s repository at https://github.com/louthy/language-ext