Library / SDK
louthy/language-ext avatar
louthy/language-ext

language-ext: a functional base class library for C#

C# pure functional programming framework - come and get declarative!

7,084 stars448 forksC#MIT

At a glance

What is it?
language-ext adds Option, Either, immutable collections, effects and traits to C#. It is for teams that want declarative, pure code inside the .NET ecosystem, and it asks you to accept its own naming conventions in return.
Who is it for?
Adopt language-ext if your team already writes C# and wants Option, Either, immutable collections and effect types in the same codebase, and if you are willing to add the global usings the README lists and to write camelCase prelude calls. Do not adopt it as a small utility package for one or two null checks; the trait and effect layers are the point, and a partial adoption leaves you with two idioms in one solution.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 36 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • louthy/language-ext7,084 ★ · +0
Star history
Repository2026-09-232026-11-14
louthy/language-ext7.1k7.1k

0 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What language-ext is for, and who it is aimed at

The README states the goal directly: to make the engineer's inertia flow toward declarative and pure functional code rather than imperative code, and it claims that using these techniques for large code-bases can reduce hidden complexity and cognitive load. That is a maintenance argument, not a performance argument. The target reader is a working C# developer on a long-lived codebase who is tired of null checks, mutable shared state and exceptions used as control flow, but who cannot move the whole product to F# or Haskell. The README anticipates that objection and answers it: C# has a state-of-the-art compiler, Visual Studio and Rider, a large open-source ecosystem, and a large hiring pool, and it already has first-class functions and lambdas. The library's framing is that with language-ext, C# gains a functional-first base class library. If your team is small, your codebase is short-lived, or your colleagues consider camelCase static methods an insult, this is the wrong tool and the README says so in advance: it will not always sit well with the seasoned C# OO programmer.

Option, Either and the prelude: the mechanism underneath

The core mechanism is static classes used as namespaces. C# has allowed `using static` since version 6, so `LanguageExt.Prelude` can expose single-term functions that read like ML-style functions rather than qualified methods. The README's own example of the language feature is `using static System.Console;` followed by `WriteLine("Hello, World");`. language-ext applies the same trick to `Some`, `None`, `Left`, `Right` and the rest of the prelude. The namespace layout carries the architecture: `LanguageExt` holds most core types, `LanguageExt.Prelude` holds the standalone functions, `LanguageExt.Traits` brings in the higher-kinded trait types and many extensions, `LanguageExt.Common` brings in the `Error` type and predefined `Errors`, and `LanguageExt.Effects` and `LanguageExt.Streaming` cover effects and streams. That is a large surface. It also means the library is not a bag of helper methods; the types are meant to compose through traits, and the payoff comes from using them together rather than picking one.

Installing language-ext from NuGet and writing a first Option

The README says to include `LanguageExt.Core.dll` in your project or grab it from NuGet, and it recommends setting up global usings. The full list it gives covers all functionality: `LanguageExt`, `LanguageExt.Common`, `LanguageExt.Traits`, `LanguageExt.Effects`, `LanguageExt.Streaming`, `LanguageExt.Pretty`, `LanguageExt.Traits.Domain`, and the static prelude. A minimum setup is shorter.

csharp
global using LanguageExt;
global using static LanguageExt.Prelude;

With those two lines in place, `Some`, `None` and the prelude functions are in scope without a namespace prefix. The library is not a single package. The README's NuGet table lists `LanguageExt.Parsec` (a port of the Haskell parsec library), `LanguageExt.Streaming` (compositional streaming types), `LanguageExt.FSharp` (interop between core types like `Option`, `List` and `Map` and their F# equivalents), `LanguageExt.Rx` (Reactive Extensions support for core types) and `LanguageExt.Sys` (an effects wrapper around the .NET System namespace that makes common IO operations pure and unit-testable). Add only the ones you need. The repository also ships samples you can read before writing your own code: `Samples/CreditCardValidation/`, `Samples/CardGame/`, `Samples/EffectsExamples/`, `Samples/Streams/` and `Samples/DomainTypesExamples/` are top-level directories under `Samples/`. The README points to issues labelled "examples / documentation" as a second source, which tells you something about how the documentation is distributed.

Where language-ext gets awkward

The naming is the first wall. The README concedes that the choice of camelCase names for a lot of functions and the seeming globalness of the library are likely to get seasoned C# heads worked up, and it argues the case rather than apologising. That is a deliberate trade: you gain prelude functions that look like a functional language, and you lose the BCL naming conventions your reviewers expect. The second wall is version churn. The recent releases are all v5.0.0 betas, from v5.0.0-beta-69 through v5.0.0-beta-78, with entries such as SourceT improvements, a StreamT non-termination issue resolved, and a fix for an indexing issue on Arr. The README's getting-started section lists v5-era namespaces including `LanguageExt.Traits` and `LanguageExt.Effects`, so code written against v4 examples will not line up with the current documentation. The third wall is documentation shape. The README is long but it is a tour, not a reference; the API reference lives at a separate generated site, and a meaningful share of worked examples sits in GitHub issues rather than in the repository. If your team needs a single canonical manual with a stable table of contents, this will cost you time. Finally, the library is not archived and the last push was on 2026-10-09, so it is moving, but the release line in the repository is beta, and that is the version to evaluate.

How it differs from CSharpFunctionalExtensions

The obvious comparison is CSharpFunctionalExtensions, and the difference is scope rather than quality. CSharpFunctionalExtensions is a small set of value objects, chiefly `Result` and `Maybe`, that you can drop into an existing imperative codebase file by file. language-ext is a framework: the README describes a pure functional-programming framework that, if you squint, can look like extensions to the language itself, and the repository carries traits, monad transformers, parser combinators, streaming types, a `Pretty` layout module and a `Differencing` module. Those last four have no counterpart in a minimal result-type library. The practical consequence is adoption cost. With a small result library you change the signature of a method and move on. With language-ext you choose a namespace layout, decide whether to bring the whole prelude into scope, and accept that `Option`, `Either`, the immutable collections and the effect types are meant to be used as one vocabulary. For speed, the repository carries a `Performance.md` file and a `LanguageExt.Benchmarks/` project.

Licence, maintenance and what an upgrade actually costs

The licence is MIT, which permits commercial use and modification with the usual attribution requirement; this is a summary of the identifier in the repository metadata, not legal advice, and your own counsel should confirm obligations for your distribution model. Maintenance signals are mixed in a specific way. The repository is not archived and the last push was on 2026-10-09, so the project is being worked on. The recent releases, however, are all v5.0.0 betas, the newest being v5.0.0-beta-78 on 2026-10-09, which means the current line is pre-release. There is a `Major Version Release Notes/` directory at the top level, which is where breaking changes between major versions are recorded; read it before moving a production solution from v4 to v5, because the namespace list in the README's getting-started section is v5-shaped. The upgrade cost is not the package reference. It is the call sites: every `Option`, `Either` and effect expression written against the older API has to be recompiled and, where the trait or effect layer changed, rewritten. Budget for that as a migration, not a version bump.

Editorial conclusion

Adopt language-ext if your team already writes C# and wants Option, Either, immutable collections and effect types in the same codebase, and if you are willing to add the global usings the README lists and to write camelCase prelude calls. Do not adopt it as a small utility package for one or two null checks; the trait and effect layers are the point, and a partial adoption leaves you with two idioms in one solution. Before committing, check the release notes for v5.0.0-beta-78 and earlier betas, because the README documents v5 namespaces that differ from v4, and confirm which of the NuGet packages you actually need: LanguageExt.Core alone does not include LanguageExt.Sys, LanguageExt.Parsec or LanguageExt.Streaming.

Frequently asked questions

What is language-ext in C#?

It is a pure functional-programming framework for C# that provides a functional-first base class library, including Option and Either types, immutable collections, effects, traits and parser combinators. The README describes the goal as making an engineer's inertia flow toward declarative and pure functional code rather than imperative code.

How do I install language-ext from NuGet?

The README says to include LanguageExt.Core.dll in your project or grab it from NuGet, and it recommends adding global usings; the minimum it gives is LanguageExt plus the static LanguageExt.Prelude. Companion packages such as LanguageExt.Sys, LanguageExt.Parsec, LanguageExt.Rx, LanguageExt.FSharp and LanguageExt.Streaming are listed separately in the README's NuGet table.

What is the difference between language-ext and CSharpFunctionalExtensions?

language-ext is a framework with traits, monad transformers, parser combinators, streaming types, Pretty and Differencing, not a small result-type helper. The README frames it as a functional-first base class library for C# rather than a set of value objects.

Does language-ext work with F#?

The README lists a LanguageExt.FSharp package that provides interop between core LanguageExt types such as Option, List and Map and their F# equivalents, as well as interop between core BCL types and F#. It is a separate NuGet package from LanguageExt.Core.

What do I need to set up before using language-ext?

The README recommends global usings. The full list that covers all functionality is LanguageExt, LanguageExt.Common, LanguageExt.Traits, LanguageExt.Effects, LanguageExt.Streaming, LanguageExt.Pretty, LanguageExt.Traits.Domain and the static LanguageExt.Prelude; a minimum setup is LanguageExt plus the static prelude.

Official sources

  1. Issues
  2. License: MIT
  3. louthy/language-ext on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/louthy-language-ext.svg)](https://hysenlabs.com/projects/louthy-language-ext)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/louthy-language-ext.svg)](https://hysenlabs.com/projects/louthy-language-ext)

Was this useful?