1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//! This crate implements a mechanism to fake higher kinded types in a limited //! way in Rust with a minimum of boilerplate. //! //! # But Why? //! //! If you ever had a trait `T<A>` and wanted to swap the type parameter out in //! a generic way to produce a type `T<B>` in the trait's type signatures, //! there's no straightforward way to do this currently in Rust, because this //! would require Rust's type system to support higher kinded types. It can deal //! with `T<A>` but it can't deal with the concept of just `T` where the type //! parameter is yet unspecified (what's known as a type constructor - think of //! it as a function which takes a type parameter, like `A`, and returns a //! concrete type `T<A>`). //! //! `higher` provides the trait `Lift` which, when given a type `T<A>` which //! implements `Lift<A, B>`, will let you derive the concrete type `T<B>`. This //! needs to be implemented for any `T<A>` which needs `Lift`ing, but the //! [`higher-derive`][higher-derive] crate provides a custom derive for it, so //! that you can quickly add it to your own types without boilerplate: //! //! ```nocompile //! #[derive(Lift)] //! enum MyLittleOption<A> { //! Definitely(A), //! NotReally, //! } //! ``` //! //! Now, to convert from `T<A>` to `T<B>`, you can get the `Target1` associated //! type out of the `Lift` trait: //! //! ```nocompile //! <MyLittleOption<A> as Lift<A, B>>::Target1 //! // this resolves to MyLittleOption<B> //! ``` //! //! There is also the `Lift3<A, B, C>` trait, which is also generated by the //! `Lift` derive, which lets you go from `T<A>` to both `T<B>` and `T<C>` in //! one go. This is useful if you need an intermediate type in one of your type //! signatures, for instance a zip or merge function: `Fn(T<A>, T<B>) -> T<C>`. //! //! Here is how to use the above example type with `Lift3`: //! //! ```nocompile //! <MyLittleOption<A> as Lift3<A, B, C>>::Target2 //! // this resolves to MyLittleOption<B> //! <MyLittleOption<A> as Lift3<A, B, C>>::Target1 //! // this resolves to MyLittleOption<C> //! //! // the numbers go from right to left, so Target1 = C and Target2 = B. //! ``` //! //! Further, there's the `Bilift<A, B, C, D>` trait, for when you have two type //! parameters to generalise over. This one takes you from `T<A, B>` to `T<C, //! D>`. There's no corresponding `Bilift3` trait as yet, because I haven't //! found a practical need for it yet. //! //! There's a corresponding derive for `Bilift`: //! //! ```nocompile //! #[derive(Bilift)] //! enum MyLittleResult<A, E> { //! Grand(A), //! NotGrand(E), //! } //! ``` //! //! And, to get the derived type out of the `Bilift`: //! //! ```nocompile //! <MyLittleResult<A, B> as Bilift<A, B, C, D>>::Target1 //! // this resolves to MyLittleResult<C, D> //! ``` //! //! # Yes, But Why, Really? //! //! Because sometimes one just gets homesick for Haskell and wants to implement //! the `Functor` hierarchy. You'll find this in the `higher-cat` crate. It's //! not really very suited for writing good Rust code, but it makes Haskell //! programmers feel happy and it has a lot of funny words. //! //! [higher-derive]: https://docs.rs/crate/higher-derive mod lift; pub use crate::lift::{Lift, Lift3}; mod bilift; pub use crate::bilift::Bilift; /// You'd better be sure about what you're doing before using this. pub(crate) fn unsafe_coerce<A, B>(mut a: A) -> B { unsafe { let ptr = &mut a as *mut _ as *mut B; let out = ::std::ptr::read(ptr); ::std::mem::forget(a); out } }