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`).
12//!
13//! `fp-library` aims to bridge this gap by providing:
14//!
15//! 1. A robust encoding of HKTs in stable Rust.
16//! 2. A comprehensive set of standard type classes (`Functor`, `Monad`, `Traversable`, etc.).
17//! 3. Zero-cost abstractions that respect Rust's performance characteristics.
18//!
19//! ## Examples
20//!
21//! ### Using `Functor` with `Option`
22//!
23//! The brand is inferred automatically from the container type:
24//!
25//! ```
26//! use fp_library::functions::*;
27//!
28//! // Brand inferred from Option<i32>
29//! let y = map(|i: i32| i * 2, Some(5));
30//! assert_eq!(y, Some(10));
31//!
32//! // Brand inferred from &Vec<i32> (by-reference dispatch)
33//! let v = vec![1, 2, 3];
34//! let y = map(|i: &i32| *i + 10, &v);
35//! assert_eq!(y, vec![11, 12, 13]);
36//! ```
37//!
38//! For types with multiple brands (e.g., `Result`), use the `explicit` variant:
39//!
40//! ```
41//! use fp_library::{
42//! brands::*,
43//! functions::explicit::*,
44//! };
45//!
46//! let y = map::<ResultErrAppliedBrand<&str>, _, _, _, _>(|i| i * 2, Ok::<i32, &str>(5));
47//! assert_eq!(y, Ok(10));
48//! ```
49//!
50//! ### Monadic Do-Notation with `m_do!`
51//!
52//! The `m_do!` macro provides Haskell/PureScript-style do-notation for flat monadic code.
53//! It desugars `<-` binds into nested [`bind`](functions::bind) calls.
54//!
55//! ```
56//! use fp_library::{brands::*, functions::*, m_do};
57//!
58//! // Inferred mode: brand inferred from container types
59//! let result = m_do!({
60//! x <- Some(5);
61//! y <- Some(x + 1);
62//! let z = x * y;
63//! Some(z)
64//! });
65//! assert_eq!(result, Some(30));
66//!
67//! // Explicit mode: for ambiguous types or when pure() is needed
68//! let result = m_do!(VecBrand {
69//! x <- vec![1, 2];
70//! y <- vec![10, 20];
71//! pure(x + y)
72//! });
73//! assert_eq!(result, vec![11, 21, 12, 22]);
74//! ```
75//! ## Features
76//!
77//! For a detailed breakdown of all features, type class hierarchies,
78//! data types, and macros, see the [Features documentation][crate::docs::features].
79//!
80//! ## How it Works
81//!
82//! **Higher-Kinded Types:** The library encodes HKTs using lightweight higher-kinded polymorphism
83//! (the "Brand" pattern). Each type constructor has a zero-sized brand type (e.g., `OptionBrand`)
84//! that implements `Kind` traits mapping brands back to concrete types.
85//! See [Higher-Kinded Types][crate::docs::hkt].
86//!
87//! **Brand Inference:** `InferableBrand` traits provide the reverse mapping (concrete type -> brand),
88//! letting the compiler infer brands automatically. `trait_kind!` and `impl_kind!` generate both
89//! mappings. See [Brand Inference][crate::docs::brand_inference].
90//!
91//! **Val/Ref Dispatch:** Each free function routes to either a by-value or by-reference trait method
92//! based on the closure's argument type (or container ownership for closureless operations). Dispatch
93//! and brand inference compose through the shared `FA` type parameter.
94//! See [Val/Ref Dispatch][crate::docs::dispatch].
95//!
96//! **Zero-Cost Abstractions:** Core operations use uncurried semantics with `impl Fn` for static
97//! dispatch and zero heap allocation. Dynamic dispatch (`dyn Fn`) is reserved for cases where
98//! functions must be stored as data.
99//! See [Zero-Cost Abstractions][crate::docs::zero_cost].
100//!
101//! **Lazy Evaluation:** A granular hierarchy of lazy types (`Thunk`, `Trampoline`, `Lazy`) lets you
102//! choose trade-offs between stack safety, memoization, lifetimes, and thread safety. Each has a
103//! fallible `Try*` counterpart.
104//! See [Lazy Evaluation][crate::docs::lazy_evaluation].
105//!
106//! **Thread Safety & Parallelism:** A parallel trait hierarchy (`ParFunctor`, `ParFoldable`, etc.)
107//! mirrors the sequential one. When the `rayon` feature is enabled, `par_*` functions use true
108//! parallel execution.
109//! See [Thread Safety and Parallelism][crate::docs::parallelism].
110//!
111//! ## Documentation
112//!
113//! - [Features & Type Class Hierarchy][crate::docs::features]
114//! - [Higher-Kinded Types][crate::docs::hkt]
115//! - [Brand Inference][crate::docs::brand_inference]
116//! - [Val/Ref Dispatch][crate::docs::dispatch]
117//! - [Zero-Cost Abstractions][crate::docs::zero_cost]
118//! - [Pointer Abstraction][crate::docs::pointer_abstraction]
119//! - [Lazy Evaluation][crate::docs::lazy_evaluation]
120//! - [Coyoneda Implementations][crate::docs::coyoneda]
121//! - [Thread Safety & Parallelism][crate::docs::parallelism]
122//! - [Limitations and Workarounds][crate::docs::limitations_and_workarounds]
123//! - [Project Structure][crate::docs::project_structure]
124//! - [Architecture & Design][crate::docs::architecture]
125//! - [Optics Analysis][crate::docs::optics_analysis]
126//! - [Profunctor Analysis][crate::docs::profunctor_analysis]
127//! - [Std Library Coverage][crate::docs::std_coverage_checklist]
128//!
129//! ## Crate Features
130//!
131//! - **`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.
132//! - **`serde`**: Enables serialization and deserialization support for pure data types using the [serde](https://github.com/serde-rs/serde) library.
133//! - **`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.
134
135extern crate fp_macros;
136
137pub mod brands;
138pub mod classes;
139pub mod dispatch;
140pub mod docs;
141pub mod functions;
142pub mod kinds;
143pub mod types;
144pub(crate) mod utils;
145
146pub use fp_macros::*;