Functional programming in C++
The purpose of this library is to exercise an approach to functional programming in C++ on top of the existing std C++ vocabulary types (such as std::expected and std::optional), with the aim of eventually extending the future versions of the C++ standard library with the functionality found to work well.
The approach is to take the existing std types in the C++ standard library (when appropriate) and extend them (via inheritance) with the facilities useful in writing functional style programs. Eventually, the proposed functionality will be (hopefully) folded into the existing std types and new std types will be added.
This library requires a very modern implementation of the C++ library which implements monadic operations in std::optional and std::expected, as defined in ISO/IEC 14882:2023. Currently, such implementations are provided with gcc 13 and clang 18, which are the recommended compilers for this project. A suggested approach to access the most recent version of the compiler (when it is not available in the operating system) is to use a devcontainer when working with this project. Alternatively take a look at Nix and nix/README.md.
This library requires standardized type ordering, which currently is a proposed C++26 feature and is not implemented by any compiler. Currently, the library relies on an internal, naive implementation of such a feature which is not expected to work with unnamed types, types without linkage etc.
The maintainers will aim to maintain compatibility with the proposed changes in the C++ standard library, rather than with the existing uses of the code in this repo. In practice, this means that all code in this repo should be considered "under intensive development and unstable" until the standardization of the proposed facilities.
The maintainers are unable to guarantee that no significant refactoring will ever take place. The opposite is to be expected, since the process of standardization of any additions to the C++ standard library typically involves a fair number of changes and improvements, some of them quite fundamental. This includes all kinds of interfaces and names in this library, which until the moment of standardization are only proposed.
Releases are numbered 0.y.z and will stay below 1.0.0 for the foreseeable future. SemVer treats any 0.y.z version as unstable — anything may change — so libfn narrows that into a usable contract:
- a bump in
yis a breaking change (API and/or ABI); - a bump in
zis a bug fix or a purely additive extension: the API and ABI stay compatible, but inline function definitions may change.
Because the library is header-only, use a single libfn version per binary. Mixing versions in one program is an ODR violation — and that includes two z releases of the same y line, whose inline definitions may differ even though the ABI matches.
See CONTRIBUTING.md for the development environment, building, testing, versioning, and the pre-commit workflow.
- Gašper Ažman, for providing the inspiration in "(Fun)ctional C++ and the M-word"
- Bartosz Milewski, for taking the time to explain parametrised and graded monads and effect systems
- Ripple, for allowing the main author the time to work on this library