Skip to main content

fp_library/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3#![allow(clippy::tabs_in_doc_comments)]
4
5//! # fp-library
6//!
7//! A functional programming library for Rust featuring your favourite higher-kinded types and type classes.
8//!
9//! ## Motivation
10//!
11//! 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.
12//!
13//! ## Examples
14//!
15//! ### Using `Functor` with `Option`
16//!
17//! The brand is inferred automatically from the container type:
18//!
19//! ```
20//! use fp_library::functions::*;
21//!
22//! // Brand inferred from Option<i32>
23//! let y = map(|i: i32| i * 2, Some(5));
24//! assert_eq!(y, Some(10));
25//!
26//! // Brand inferred from &Vec<i32> (by-reference dispatch)
27//! let v = vec![1, 2, 3];
28//! let y = map(|i: &i32| *i + 10, &v);
29//! assert_eq!(y, vec![11, 12, 13]);
30//! ```
31//!
32//! For types with multiple brands (e.g., `Result`, which can be viewed as a functor over
33//! either its `Ok` or `Err` type), annotate the closure's input type to disambiguate
34//! which brand applies:
35//!
36//! ```
37//! use fp_library::functions::*;
38//!
39//! // Closure annotation pins A = i32, selecting ResultErrAppliedBrand<&str>
40//! let y = map(|i: i32| i * 2, Ok::<i32, &str>(5));
41//! assert_eq!(y, Ok(10));
42//! ```
43//!
44//! For diagonal cases (e.g., `Result<T, T>`) where the closure cannot disambiguate,
45//! use the `explicit` variant with a turbofish:
46//!
47//! ```
48//! use fp_library::{
49//! 	brands::*,
50//! 	functions::explicit::*,
51//! };
52//!
53//! let y = map::<ResultErrAppliedBrand<i32>, _, _, _, _>(|i| i * 2, Ok::<i32, i32>(5));
54//! assert_eq!(y, Ok(10));
55//! ```
56//!
57//! ### Monadic Do-Notation with `m_do!`
58//!
59//! The `m_do!` macro provides Haskell/PureScript-style do-notation for flat monadic code.
60//! It desugars `<-` binds into nested [`bind`](functions::bind) calls.
61//!
62//! ```
63//! use fp_library::{brands::*, functions::*, m_do};
64//!
65//! // Inferred mode: brand inferred from container types
66//! let result = m_do!({
67//! 	x <- Some(5);
68//! 	y <- Some(x + 1);
69//! 	let z = x * y;
70//! 	Some(z)
71//! });
72//! assert_eq!(result, Some(30));
73//!
74//! // Explicit mode: for ambiguous types or when pure() is needed
75//! let result = m_do!(VecBrand {
76//! 	x <- vec![1, 2];
77//! 	y <- vec![10, 20];
78//! 	pure(x + y)
79//! });
80//! assert_eq!(result, vec![11, 21, 12, 22]);
81//! ```
82//! ## Features
83//!
84//! For a detailed breakdown of all features, type class hierarchies,
85//! data types, and macros, see the [Features documentation][crate::docs::features].
86//!
87//! ## How it Works
88//!
89//! **Higher-Kinded Types:** The library encodes HKTs using lightweight higher-kinded polymorphism
90//! (the "Brand" pattern). Each type constructor has a zero-sized brand type (e.g., `OptionBrand`)
91//! that implements `Kind` traits mapping brands back to concrete types.
92//! See [Higher-Kinded Types][crate::docs::hkt].
93//!
94//! **Dispatch System:** Free functions like `map` and `bind` infer the brand from the container
95//! type and route to by-value or by-reference trait methods automatically, so most call sites
96//! need no turbofish. For details, see [Brand Inference][crate::docs::brand_inference],
97//! [Val/Ref Dispatch][crate::docs::dispatch], and
98//! [Brand Dispatch Traits][crate::docs::brand_dispatch_traits].
99//!
100//! **Zero-Cost Abstractions:** Core operations use uncurried semantics with `impl Fn` for static
101//! dispatch and zero heap allocation. Dynamic dispatch (`dyn Fn`) is reserved for cases where
102//! functions must be stored as data.
103//! See [Zero-Cost Abstractions][crate::docs::zero_cost].
104//!
105//! **Lazy Evaluation:** A granular hierarchy of lazy types (`Thunk`, `Trampoline`, `Lazy`) lets you
106//! choose trade-offs between stack safety, memoization, lifetimes, and thread safety. Each has a
107//! fallible `Try*` counterpart.
108//! See [Lazy Evaluation][crate::docs::lazy_evaluation].
109//!
110//! **Thread Safety & Parallelism:** A parallel trait hierarchy (`ParFunctor`, `ParFoldable`, etc.)
111//! mirrors the sequential one. When the `rayon` feature is enabled, `par_*` functions use true
112//! parallel execution.
113//! See [Thread Safety and Parallelism][crate::docs::parallelism].
114//!
115//! ## Documentation
116//!
117//! - [Features & Type Class Hierarchy][crate::docs::features]: Full feature list with hierarchy diagrams.
118//! - [Higher-Kinded Types][crate::docs::hkt]: The Brand pattern and HKT encoding.
119//! - [Brand Inference][crate::docs::brand_inference]: User guide for turbofish-free dispatch and multi-brand inference.
120//! - [Val/Ref Dispatch][crate::docs::dispatch]: User guide for unified by-value and by-reference function dispatch.
121//! - [Brand Dispatch Traits][crate::docs::brand_dispatch_traits]: Implementer reference for trait shapes, Marker invariant, and inference resolution.
122//! - [Zero-Cost Abstractions][crate::docs::zero_cost]: Uncurried semantics and static dispatch.
123//! - [Pointer Abstraction][crate::docs::pointer_abstraction]: Pointer hierarchy, `FnBrand<P>`, and shared memoization.
124//! - [Lazy Evaluation][crate::docs::lazy_evaluation]: Guide to the lazy evaluation and memoization types.
125//! - [Coyoneda Implementations][crate::docs::coyoneda]: Trade-offs between the four free functor variants.
126//! - [Thread Safety & Parallelism][crate::docs::parallelism]: Parallel trait hierarchy and rayon support.
127//! - [Limitations and Workarounds][crate::docs::limitations_and_workarounds]: Rust type system constraints and how the library addresses them.
128//! - [Project Structure][crate::docs::project_structure]: Module layout and dependency graph.
129//! - [Architecture & Design][crate::docs::architecture]: Design decisions and documentation conventions.
130//! - [Optics Analysis][crate::docs::optics_analysis]: Optics coverage comparison with PureScript.
131//! - [Profunctor Analysis][crate::docs::profunctor_analysis]: Profunctor class hierarchy comparison with PureScript.
132//! - [Std Library Coverage][crate::docs::std_coverage_checklist]: Type class coverage for standard library types.
133//! - [Benchmarks][crate::docs::benchmarking]: Performance results, graphs, and benchmark coverage.
134//! - [References][crate::docs::references]: Papers, libraries, and resources that informed this project.
135//!
136//! ## Crate Features
137//!
138//! - **`rayon`**: Enables true parallel execution for `par_*` functions using the [rayon](https://github.com/rayon-rs/rayon) library. Without this feature, `par_*` functions fall back to sequential equivalents.
139//! - **`serde`**: Enables serialization and deserialization support for pure data types using the [serde](https://github.com/serde-rs/serde) library.
140//! - **`stacker`**: Enables adaptive stack growth for deep `Coyoneda`, `RcCoyoneda`, and `ArcCoyoneda` map chains via the [stacker](https://github.com/rust-lang/stacker) crate. Without this feature, deeply chained maps can overflow the stack.
141
142extern crate fp_macros;
143// Allow the proc macro output to reference this crate via the absolute
144// path `::fp_library::dispatch::{Val, Ref}`. Without this, `::fp_library`
145// only resolves in external crates, not inside fp-library itself.
146extern crate self as fp_library;
147
148pub mod brands;
149pub mod classes;
150pub mod dispatch;
151pub mod docs;
152pub mod functions;
153pub mod kinds;
154pub mod types;
155pub(crate) mod utils;
156
157pub use fp_macros::*;