Skip to main content

Crate fp_library

Crate fp_library 

Source
Expand description

§fp-library

A functional programming library for Rust featuring your favourite higher-kinded types and type classes.

§Motivation

Rust is a multi-paradigm language with strong functional programming features like iterators, closures, and algebraic data types. However, it lacks native support for Higher-Kinded Types (HKT), which limits the ability to write generic code that abstracts over type constructors (e.g., writing a function that works for any Monad, whether it’s Option, Result, or Vec). fp-library aims to bridge this gap.

§Examples

§Using Functor with Option

The brand is inferred automatically from the container type:

use fp_library::functions::*;

// Brand inferred from Option<i32>
let y = map(|i: i32| i * 2, Some(5));
assert_eq!(y, Some(10));

// Brand inferred from &Vec<i32> (by-reference dispatch)
let v = vec![1, 2, 3];
let y = map(|i: &i32| *i + 10, &v);
assert_eq!(y, vec![11, 12, 13]);

For types with multiple brands (e.g., Result, which can be viewed as a functor over either its Ok or Err type), annotate the closure’s input type to disambiguate which brand applies:

use fp_library::functions::*;

// Closure annotation pins A = i32, selecting ResultErrAppliedBrand<&str>
let y = map(|i: i32| i * 2, Ok::<i32, &str>(5));
assert_eq!(y, Ok(10));

For diagonal cases (e.g., Result<T, T>) where the closure cannot disambiguate, use the explicit variant with a turbofish:

use fp_library::{
	brands::*,
	functions::explicit::*,
};

let y = map::<ResultErrAppliedBrand<i32>, _, _, _, _>(|i| i * 2, Ok::<i32, i32>(5));
assert_eq!(y, Ok(10));

§Monadic Do-Notation with m_do!

The m_do! macro provides Haskell/PureScript-style do-notation for flat monadic code. It desugars <- binds into nested bind calls.

use fp_library::{brands::*, functions::*, m_do};

// Inferred mode: brand inferred from container types
let result = m_do!({
	x <- Some(5);
	y <- Some(x + 1);
	let z = x * y;
	Some(z)
});
assert_eq!(result, Some(30));

// Explicit mode: for ambiguous types or when pure() is needed
let result = m_do!(VecBrand {
	x <- vec![1, 2];
	y <- vec![10, 20];
	pure(x + y)
});
assert_eq!(result, vec![11, 21, 12, 22]);

§Features

For a detailed breakdown of all features, type class hierarchies, data types, and macros, see the Features documentation.

§How it Works

Higher-Kinded Types: The library encodes HKTs using lightweight higher-kinded polymorphism (the “Brand” pattern). Each type constructor has a zero-sized brand type (e.g., OptionBrand) that implements Kind traits mapping brands back to concrete types. See Higher-Kinded Types.

Dispatch System: Free functions like map and bind infer the brand from the container type and route to by-value or by-reference trait methods automatically, so most call sites need no turbofish. For details, see Brand Inference, Val/Ref Dispatch, and Brand Dispatch Traits.

Zero-Cost Abstractions: Core operations use uncurried semantics with impl Fn for static dispatch and zero heap allocation. Dynamic dispatch (dyn Fn) is reserved for cases where functions must be stored as data. See Zero-Cost Abstractions.

Lazy Evaluation: A granular hierarchy of lazy types (Thunk, Trampoline, Lazy) lets you choose trade-offs between stack safety, memoization, lifetimes, and thread safety. Each has a fallible Try* counterpart. See Lazy Evaluation.

Thread Safety & Parallelism: A parallel trait hierarchy (ParFunctor, ParFoldable, etc.) mirrors the sequential one. When the rayon feature is enabled, par_* functions use true parallel execution. See Thread Safety and Parallelism.

§Documentation

§Crate Features

  • rayon: Enables true parallel execution for par_* functions using the rayon library. Without this feature, par_* functions fall back to sequential equivalents.
  • serde: Enables serialization and deserialization support for pure data types using the serde library.
  • stacker: Enables adaptive stack growth for deep Coyoneda, RcCoyoneda, and ArcCoyoneda map chains via the stacker crate. Without this feature, deeply chained maps can overflow the stack.

Modules§

brands
Brands represent higher-kinded (unapplied/partially-applied) forms of types, as opposed to concrete types, which are fully-applied.
classes
Defines traits for common algebraic structures and functional abstractions, such as Functor, Applicative and Monad.
dispatch
Dispatch infrastructure for unified free functions that route to either by-value or by-reference trait methods based on the closure’s argument type.
docs
Design documentation for fp-library.
functions
The primary API for calling type class operations as free functions.
kinds
Kind and InferableBrand traits for higher-kinded type simulation.
types
Concrete data types, their corresponding implementations and type aliases.

Macros§

Apply
Applies a brand to type arguments.
Kind
Generates the name of a Kind trait based on its signature.
a_do
Applicative do-notation.
generate_function_re_exports
Generates re-exports for all public free functions in a directory.
generate_trait_re_exports
Generates re-exports for all public traits in a directory.
impl_kind
Implements a Kind trait and its InferableBrand trait for a brand.
include_documentation
Includes a markdown file with relative .md links rewritten to rustdoc intra-doc links.
m_do
Monadic do-notation.
trait_kind
Defines a new Kind trait and its corresponding InferableBrand trait.

Attribute Macros§

document_examples
Inserts a ### Examples heading and validates doc comment code blocks.
document_module
Orchestrates documentation generation for an entire module.
document_parameters
Generates documentation for a function’s parameters.
document_returns
Generates documentation for the return value of a function.
document_signature
Generates a Hindley-Milner style type signature for a function.
document_type_parameters
Generates documentation for type parameters.
kind
Adds a Kind supertrait bound to a trait definition.