fp-macros
Procedural macros for the fp-library crate.
This crate provides a suite of macros designed to facilitate working with Higher-Kinded Types (HKT) in Rust. It automates the generation of Kind traits, simplifies their implementation for specific Brand types, and provides a convenient syntax for type application.
Installation
Add this to your Cargo.toml:
[]
= "0.3"
Note: If you are using
fp-library, these macros are already re-exported at the crate root. You only need to add this dependency if you are using the macros independently.
Macros
def_kind!
Defines a new Kind trait based on a Higher-Kinded Type signature.
This macro generates a trait definition for a Higher-Kinded Type signature. It takes a list of associated type definitions, similar to a trait definition.
Syntax:
def_kind!;
Examples:
use def_kind;
// Simple definition
def_kind!;
// Definition with bounds and lifetimes
def_kind!;
// Multiple associated types
def_kind!;
impl_kind!
Simplifies the implementation of a generated Kind trait for a specific brand type. It infers the correct Kind trait to implement based on the signature of the associated types provided in the block.
The signature (names, parameters, and bounds) of the associated types must match the definition used in def_kind! or Kind! to ensure the correct trait is implemented.
Syntax:
impl_kind!
Examples:
use impl_kind;
;
// Simple implementation
impl_kind!
;
// Implementation with generics
impl_kind!
// Implementation with where clause and multiple types
impl_kind!
Apply!
Applies a Brand to type arguments.
This macro projects a Brand type to its concrete type using the appropriate Kind trait. It uses a syntax that mimics a fully qualified path, where the Kind trait is specified by its signature.
Syntax:
Apply!
Brand: The brand type (e.g.,OptionBrand).KindSignature: A list of associated type definitions defining theKindtrait schema.AssocType: The associated type to project (e.g.,Of).Args: The concrete arguments to apply.
Examples:
use Apply;
// Applies MyBrand to lifetime 'static and type String.
type Concrete = Apply!;
// Applies MyBrand to a generic type T with bounds.
type Concrete = Apply!;
// Complex example with lifetimes, types, and output bounds.
type Concrete = Apply!;
// Use a custom associated type for projection.
type Concrete = Apply!;
Kind!
Generates the name of a Kind trait based on its signature.
This macro takes a list of associated type definitions, similar to a trait definition. It is primarily used internally by other macros (like Apply!) but can be useful when you need to refer to the generated trait name directly (e.g., in bounds where macros aren't allowed).
Syntax:
Kind!
Examples:
use Kind;
// Simple signature
let name = Kind!;
// Signature with bounds and lifetimes
let name = Kind!;
Limitations:
Due to Rust syntax restrictions, this macro cannot be used directly in positions where a concrete path is expected by the parser, such as:
- Supertrait bounds:
trait MyTrait: Kind!(...) {}(Invalid) - Type aliases:
type MyKind = Kind!(...);(Invalid) - Trait aliases:
trait MyKind = Kind!(...);(Invalid)
In these cases, you must use the generated name directly (e.g., Kind_...).
The generated trait name is a deterministic hash of the signature (e.g., Kind_a1b2c3d4e5f67890). To find the exact name for use in restricted positions, you can inspect the expanded code (using cargo expand) or check the compiler error output when attempting to use the macro in a valid position first.
License
This project is licensed under the Blue Oak Model License 1.0.0.