1 unstable release
0.1.0 | Dec 3, 2020 |
---|
#1494 in Rust patterns
44KB
850 lines
Lifted
Higher-kinded types for Rust. Implementation based on modifications to Liebow-Feeser's method, winding up at the same scheme described by Yallop & White.
Quickstart
Say you'd like to write a higher-kinded trait such as Functor
. We can
imagine it might someday look a bit like this:
trait Functor<A> {
fn fmap<B, F: Fn(A) -> B>(me: Self<A>, f: F) -> Self<B>;
}
This isn't valid today, but with some minor changes we can write it:
use lifted::K1;
trait Functor {
fn fmap<A, B, F: Fn(A) -> B>(me: K1<Self, A>, f: F) -> K1<Self, B>;
}
There are two key visible changes, and one hidden one:
- rather than hypothetically parameterizing our
Functor
trait, we've moved the type parameter to the method itself, - rather than the hypothetical native
Self<B>
, we use aK1<Self, B>
wrapper struct, and - rather than hypothetically implementing the trait for a half-baked
type (e.g.
Vec
), we implement it for the HKT formVecC
.
(Note that, while the term HKT form is borrowed from generic_std
,
the use of them here was discovered independently. On further review,
the concept closely matches the brand from Yallop & White.)
The first two are more or less self-explanatory, but the third could use an illustration to clarify. Let's implement it!
use lifted::Kind1;
// Define the higher-kinded form of `Vec`
pub struct VecC;
// Specify how to construct a type instance
impl<T> Kind1<T> for VecC {
type Inner = Vec<T>;
}
impl Functor for VecC {
fn fmap<A, B, F: Fn(A) -> B>(me: K1<Self, A>, f: F) -> K1<Self, B> {
let me = me.into_inner(); // unwrap the Vec<A>
let you = me.map(f); // map the Vec<A> to a Vec<B>
K1::new(you) // rewrap the Vec<B>
}
}
For more details, please consult the API Documentation.
Documentation
API Docs
API docs are hosted on docs.rs:
Minimum Supported Rust Version
This crate makes use of no exotic language features, and so can support even very old versions of stable Rust. It has been tested successfully with Rust 1.35. (Once we get around to setting up CI, we will verify this MSRV with CI testing).
Comparison to other crates
- Crate:
generic_std
- Purpose: generic traits for
std
types - Implementation: modified Smith's method, constructs a type instance from an HKT form
- Maintenance: one experimental release
- Notes: also considers lifetime kinds!
- Notes: no concrete instance handling
- Purpose: generic traits for
- Crate:
fp-core
- Purpose: a library for functional programming in Rust
- Implementation:
HKT
trait constructs a type instance from another instance, macro to implement - Maintenance: no changes in the past year
- Crate:
rats
- Purpose: an experimental, type-level functional programming library for Rust
- Implementation: a god enum, traits, and type brands in some strange tango
- Maintenance: no changes in the past 2 years
- Crate:
higher
- Purpose: fake higher-kinded types with a minimum of boilerplate
- Implementation:
Lift
trait constructs a type instance from another instance, derive macro to implement - Maintenance: one change in the past year
- Crate:
kinder
- Purpose: algebraic structure and emulation of higher-order types
- Implementation:
Higher
trait constructs a type instance from another instance, macro to implement - Maintenance: no changes in the past 4 years
- Crate:
archery
- Purpose: abstract over atomicity of reference-counted pointers
- Implementation: also based on Liebow-Feeser
- Maintenance: active
Contributing
I'm happy to see any and all contributions, including bug reports, usability suggestions, patches, or angry yet well-intentioned rants. You are encouraged to report issues to the official issue tracker and send any questions or patches to the mailing list. Pull requests to the GitHub mirror are also acceptable.