higher_kinded_types/_lib.rs
1//! [ForLifetime]: trait@ForLifetime
2#![doc = include_str!("../README.md")]
3#![no_std]
4#![forbid(unsafe_code)]
5#![allow(type_alias_bounds, uncommon_codepoints, unused_braces)]
6#![allow(
7 // in case `crate::ForLt!` does not resolve, we have the `crate::hkt_macro::*` fallback.
8 macro_expanded_macro_exports_accessed_by_absolute_paths,
9)]
10#![cfg_attr(feature = "better-docs",
11 feature(decl_macro, doc_cfg, trait_alias),
12)]
13#![cfg_attr(feature = "fn_traits",
14 feature(unboxed_closures),
15)]
16
17#[macro_use]
18extern crate macro_rules_attribute;
19
20/// The crate's prelude.
21pub
22mod prelude {
23 #[doc(no_inline)]
24 pub use crate::{
25 advanced::{extra_arities::For, ForLifetimeMaybeUnsized},
26 ForLifetime,
27 ForLifetime as ForLt,
28 };
29 #[doc(inline)]
30 pub use crate::hkt_macro::ForLt;
31}
32
33// macro internals
34#[doc(hidden)] /** Not part of the public API */ pub
35mod ඞ {
36 pub use {
37 ::core, // or `std`
38 crate::{
39 advanced::{
40 extra_arities::{
41 for_lt_and_lt::WithLifetimes,
42 },
43 },
44 },
45 };
46 #[cfg(feature = "fn_traits")]
47 pub use {
48 crate::{
49 fn_traits::{
50 Input as r#for,
51 Input as __,
52 },
53 },
54 };
55
56 /// Do not use this type!
57 pub
58 struct ForLt<T : ?Sized>(
59 ::core::marker::PhantomData<fn(&()) -> &T>,
60 ǃ,
61 );
62
63 /// Do not use this type!
64 pub
65 struct ForLtAndLt<T : ?Sized>(
66 ::core::marker::PhantomData<fn(&()) -> &T>,
67 ǃ,
68 );
69
70 use ::never_say_never::Never as ǃ;
71}
72
73
74#[cfg_attr(feature = "docs-rs",
75 doc(cfg(advanced)),
76)]
77pub
78mod advanced;
79
80#[cfg(feature = "fn_traits")]
81mod fn_traits;
82
83#[allow(unused_imports)]
84#[doc(inline)]
85pub use hkt_macro::ForLt;
86mod hkt_macro;
87
88mod hkt_muncher;
89
90mod utils;
91
92/// The main trait of the crate. The one expressing `: <'_>`-genericity.
93///
94/// It is expected to be used as a bound on a `<T>` generic parameter,
95/// thereby resulting in a <code><T : [ForLt]></code> generic API, which,
96/// conceptually / sort to speak, is to be read as `<T : <'_>>`.
97///
98/// That is, **a _generic API_ whose generic parameter is, in and of itself,
99/// _generic too_!**
100///
101/// - Such a "generic-generic API" is dubbed _higher-kinded_, which makes a
102/// type such as `struct Example<T: <'_>>` then be dubbed _higher-kinded
103/// type_, or **HKT**, for short.
104///
105/// From there, the whole concept of expressing genericity over
106/// `: <'_>`-generic types can also be associated with the idea and concept
107/// of higher-kinded types, much like the name of this crate indicates.
108///
109/// So, using this HKT terminology for something other than a type taking
110/// a [`: For`-bounded] generic type is, if we are to be pedantic[^haskell]
111/// about the topic, an abuse of terminology (one which I'll probably make
112/// throughout this documentation).
113///
114///
115/// [^haskell]: For Haskell enthusiasts, this [`: For`-bounded]-ness could be
116/// called "Arrow-Kinded", as in, it matches the `… -> *` kind. \
117/// \
118/// Then, an Arrow-Kinded type which has, inside the `…`, yet another
119/// Arrow-Kinded type, is what is called a Higher-Kinded Type: \
120/// \
121/// - "Arrow-Kinded Type": `… -> *`, such as `ForLt!(<'a> = &'a str) : ForLt`.
122/// - Higher-Kinded Type: `(… -> *) -> *`, such as `struct Example<T : ForLt>`.
123///
124/// [`: For`-bounded]: advanced::extra_arities
125///
126/// [ForLt]: trait@ForLt
127/// [`ForLt`]: trait@ForLt
128///
129/// It cannot be manually implemented: the only types implementing this trait
130/// are the ones produced by the [`ForLt!`] macro.
131///
132/// ## HKT Usage
133///
134/// 1. Make your API take a generic <code>\<T : [ForLifetime]\></code>
135/// parameter (conceptually, a <code>\<T : [Ofᐸᑊ_ᐳ]\></code> parameter).
136///
137/// Congratulations, you now have a _higher-kinded_ API: your API is
138/// not only generic, but it is also taking a parameter which is, in turn,
139/// generic.
140///
141/// 1. #### Callers
142///
143/// Call sites use the [`ForLt!`] macro to produce a type which they
144/// can _and must_ turbofish to such APIs. For instance:
145///
146/// - <code>[ForLt!]\(&str\)</code> for the pervasive reference case
147/// (which could also use the <code>[ForRef]\<str\></code> type alias
148/// to avoid the macro),
149///
150/// or <code>[ForLt!]\(Cow\<\'_, str\>\)</code> for more complex
151/// lifetime-infected types;
152///
153/// - <code>[ForLt!]\(u8\)</code> or other owned types work too: it is not
154/// mandatory, at the call-site, to be lifetime-infected, it is just
155/// _possible_ (maximally flexible API). See [`ForFixed`].
156///
157/// 1. #### Callee/API author
158///
159/// Make use of this nested genericity in your API!
160///
161/// Feed, somewhere, a lifetime parameter to this `T`:
162///
163/// ```rust
164/// # #[cfg(any())] macro_rules! ignore {
165/// T::Of<'some_lifetime_param>
166/// # }
167/// ```
168///
169/// There are two situations where this is handy:
170///
171/// - wanting to feed two different lifetimes to `T`:
172///
173/// ```rust
174/// use ::higher_kinded_types::ForLifetime;
175///
176/// struct Example<'a, 'b, T : ForLifetime> {
177/// a: T::Of<'a>,
178/// b: T::Of<'b>,
179/// }
180/// ```
181///
182/// - wanting to "feed a lifetime later" / to feed a
183/// `for<>`-quantified lifetime to your <code>impl [ForLt]</code> type:
184///
185/// ```rust
186/// # #[cfg(any())] macro_rules! ignore {
187/// use ::higher_kinded_types::ForLifetime as Ofᐸᑊ_ᐳ; // hopefully illustrative renaming.
188///
189/// fn slice_sort_by_key<Item, Key : Ofᐸᑊ_ᐳ> (
190/// items: &'_ mut [Item],
191/// mut get_key: impl FnMut(&'_ Item) -> Key::Of<'_>,
192/// )
193/// # }
194/// ```
195///
196/// Full example:
197///
198/// <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
199///
200/// ```rust
201/// use ::higher_kinded_types::ForLt;
202///
203/// fn slice_sort_by_key<Item, Key : ForLt> (
204/// items: &'_ mut [Item],
205/// mut get_key: impl for<'it> FnMut(&'it Item) -> Key::Of<'it>,
206/// )
207/// where
208/// for<'it> Key::Of<'it> : Ord,
209/// {
210/// items.sort_by(|a: &'_ Item, b: &'_ Item| <Key::Of<'_>>::cmp(
211/// &get_key(a),
212/// &get_key(b),
213/// ))
214/// }
215///
216/// // Demo:
217/// let clients: &mut [Client] = // …;
218/// # &mut []; struct Client { key: String, version: u8 }
219///
220/// slice_sort_by_key::<_, ForLt!(&str)>(clients, |c| &c.key); // ✅
221///
222/// // Important: owned case works too!
223/// slice_sort_by_key::<_, ForLt!(u8)>(clients, |c| c.version); // ✅
224///
225/// # #[cfg(any())] {
226/// // But the classic `sort_by_key` stdlib API fails, since it does not use HKTs:
227/// clients.sort_by_key(|c| &c.key); // ❌ Error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
228/// # }
229/// ```
230///
231/// </details>
232///
233/// ### Wait a moment; this is just a GAT! Why are you talking of HKTs?
234///
235/// Indeed, the definition of the <code>[ForLt]</code> trait is basically that
236/// of a trait featuring the simplest possible GAT:
237///
238/// ```rust
239/// trait Trait { // basic trait
240/// type Assoc<'lt>; // Associated Type which is itself Generic = GAT.
241/// }
242///
243/// struct Struct<'a, 'b, T : Trait> {
244/// a: T::Assoc<'a>,
245/// b: T::Assoc<'b>,
246/// }
247/// ```
248///
249/// Yes, the `: <'_>` signature pattern of HKTs, and GATs, from this point of
250/// view, are quite interchangeable:
251///
252/// - this whole crate is a demonstration of featuring `: <'_>` HKT idioms
253/// through a [`ForLt`] GAT trait (+ some extra `for<>`-quantifications);
254///
255/// - in a world with HKTs and `: <'_>` as a first-class construct, GATs could
256/// then just be HKT Associated Types (HATs instead of GATs 🤠).
257///
258/// ```rust ,ignore
259/// //! pseudo-code!
260/// trait LendingIterator {
261/// type Item: <'_>;
262///
263/// fn next(&mut self) -> Self::Item<'_>;
264/// }
265/// ```
266///
267/// - Real code:
268///
269/// <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
270///
271/// ```rust
272/// use ::higher_kinded_types::ForLt;
273///
274/// trait LendingIterator {
275/// /// Look ma, "no" GATs!
276/// type Item: ForLt;
277///
278/// fn next(&mut self) -> <Self::Item as ForLt>::Of<'_>;
279/// }
280/// ```
281///
282/// </details>
283///
284/// In a way, the similarity between these two paradigms is akin to that of
285/// closure _vs._ object in more classic programming: you can always pick some
286/// canonical object interface, say:
287///
288/// ```rust
289/// trait Closure<Args> {
290/// type Ret;
291///
292/// fn call(&self, _: Args) -> Self::Ret;
293/// }
294/// ```
295///
296/// and then use `Closure<Args, Ret = …>` where we currently use
297/// `Fn(Args…) -> Output`: that is, the _canonical_ `Fn…` traits can easily be
298/// polyfilled with any arbitrary trait of our choice featuring the same
299/// functional API (same method signature).
300///
301/// or, _vice versa_, never define custom traits or interfaces, and always
302/// use closures:
303///
304/// ```rust ,ignore
305/// trait Display = Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
306/// // etc.
307/// ```
308///
309/// - The astute reader may notice that we lose the _nominal typing_ aspect
310/// of our current traits, which is what lets us, for instance, distinguish
311/// between `Display` and `Debug`, even if both traits, _structurally_, are
312/// equivalent / have exactly the same function signature.
313///
314/// - In general, Rust traits go way beyond the sheer API of their
315/// methods. They can be used as (sometimes `unsafe`) marker traits, or
316/// other API promises, _etc._
317///
318/// So, closures are just one specific interface/trait shape, which we could use
319/// pervasively everywhere, if we did not mind the loss of "nominal typing" (the
320/// trait name).
321///
322/// But they're actually more: closures would not be near as useful as they are
323/// if we did not have **closure expressions**!
324///
325/// In fact, closure expressions are so handy that nowadays we have a bunch of
326/// `impl Trait` constructors that take the raw/bare API/signature as a closure,
327/// and then wrap it within the "name" of the trait:
328///
329/// - **[`Iterator`]**: from
330/// `FnMut() -> Option<Item>`
331/// using [`iter::from_fn()`][::core::iter::from_fn]
332/// - **[`Future`]**: from
333/// <code>FnMut\(\&mut [Context]\<\'_\>\) -\> [Poll]\<Output\></code>
334/// using [`future::poll_fn()`][::core::future::poll_fn];
335/// - **[`Stream`]**: from
336/// `FnMut(Acc) -> impl Future<Output = (Item, Acc)>`
337/// using [`stream::unfold()`]
338///
339/// [`Future`]: ::core::future::Future
340/// [Context]: ::core::task::Context
341/// [Poll]: ::core::task::Poll
342/// [`Stream`]: https://docs.rs/futures/^0.3.28/futures/stream/trait.Stream.html
343/// [`stream::unfold()`]: https://docs.rs/futures/^0.3.28/futures/stream/fn.unfold.html
344///
345/// And that same difference applies to arbitrary GATs _vs._ [`ForLt`]: the
346/// ability to produce _ad-hoc_ / on-demand <code>impl [ForLt]</code> types /
347/// [`ForLt`] type "expressions", thanks to the [`ForLt!`] macro, is what makes
348/// [`ForLt`] convenient and flexible, _vs._ the overly cumbersome aspect of
349/// manually using custom GATs.
350///
351/// Indeed, compare:
352///
353/// ```rust
354/// trait ForLt {
355/// type Assoc<'lt>;
356/// }
357///
358/// enum StrRef {}
359///
360/// impl ForLt for StrRef {
361/// type Assoc<'lt> = &'lt str;
362/// }
363/// ```
364///
365/// to:
366///
367/// ```rust
368/// # use ::higher_kinded_types::ForLt;
369/// type StrRef = ForLt!(<'lt> = &'lt str);
370/// ```
371///
372/// ### Conclusion
373///
374/// So, to summarize, this <code>[ForLt] = ": \<\'_\>"</code> HKT pattern is just:
375///
376/// - some GAT API having been _canonical_-ized,
377///
378/// - much like how, in the realm of closures, the `Fn(Args…) -> R` was
379/// picked (_vs._ any other signature-equivalent
380/// `Closure<Args, Ret = R>` trait);
381///
382/// - which can be "inhabited" _on demand_ / in an _ad-hoc_ fashion thanks to
383/// the <code>[ForLt!]\(\<\'input\> = Output…\)</code> macro,
384///
385/// - much like how, in the realm of closures, it is done with the
386/// `|input…| output…` closure expressions.
387///
388/// In other words:
389///
390/// > `: <'_>` and HKTs are to GATs what closures are to traits.
391///
392/// (it's the `Fn(Lifetime) -> Type` of the type realm).
393///
394/// ___
395///
396/// Finally, another observation which I find interesting, is that:
397///
398/// ```rust
399/// # use ::higher_kinded_types::ForLt;
400/// #
401/// type A = ForLt!(<'r> = &'r str);
402/// // vs.
403/// type B <'r> = &'r str;
404/// ```
405///
406/// is an annoying limitation of Rust, which happens to feature a similar
407/// distinction that certain past languages have had between values, and
408/// functions, wherein they were treated separately (rather than as first-class
409/// citizens, _i.e._, like the other values).
410///
411/// In Rust, `type B<'r> = &'r str;` suffers from this same kind of limitation,
412/// only in the type realm this time: `type B<'r> =` is a special construct,
413/// which yields a _"type" constructor_. That is, it yields some syntax, `B`, to
414/// which we can feed a lifetime `'lt`, by writing `B<'lt>`, so as to end up
415/// with a _type_.
416///
417/// **But `B`, in and of itself, _is not a type_**, even if we often call it a
418/// "generic type" by abuse of terminology.
419///
420/// Which is why it cannot be fed, _alone_, to some type-generic API that would
421/// want to be the one feeding the lifetime parameter: it does not play well
422/// with "generic generics"!
423///
424/// In this example, the only true "generic _type_", that is, the _type_ which
425/// is, itself, lifetime-generic, is `A`.
426///
427/// This is where [`ForLt!`] and HKTs, thus, shine.
428pub
429trait ForLifetime : seal::WithLifetimeForAny {
430 /// "Instantiate lifetime" / "apply/feed lifetime" operation:
431 ///
432 /// - Given <code>\<T : [ForLt]\></code>,
433 ///
434 /// `T::Of<'lt>` stands for the HKT-conceptual `T<'lt>` type.
435 ///
436 /// [ForLt]: trait@ForLt
437 type Of<'lt>;
438}
439
440mod seal {
441 pub trait WithLifetimeForAny {}
442 impl<T : ?Sized + for<'any> crate::advanced::WithLifetime<'any>> WithLifetimeForAny for T {}
443}
444
445/// Shorthand alias.
446#[doc(no_inline)]
447pub use ForLifetime as ForLt;
448
449crate::utils::cfg_match! {
450 feature = "better-docs" => (
451 /// <code>: [Ofᐸᑊ_ᐳ]</code> is a hopefully illustrative syntax that
452 /// serves as an alias for <code>: [ForLt]</code>.
453 ///
454 /// [ForLt]: trait@ForLt
455 ///
456 /// When trying to teach the notion of a HKT / "generic generic API" to
457 /// somebody who has never run into it, _e.g._, in introductory
458 /// documentation, blog posts, _etc._, the <code>: [Ofᐸᑊ_ᐳ]</code>
459 /// syntax ought to be more _intuitive_:
460 ///
461 /// ```rust
462 /// use ::higher_kinded_types::*;
463 ///
464 /// struct Example<'a, 'b, T : Ofᐸᑊ_ᐳ> {
465 /// a: T::Of<'a>,
466 /// b: T::Of<'b>,
467 /// }
468 /// ```
469 ///
470 /// - (the idea being that `: Ofᐸᑊ_ᐳ` looks quite a bit like `: Of<'_>`).
471 ///
472 /// - ⚠️ real code should nonetheless be using the <code>: [ForLt]</code>
473 /// syntax: ASCII characters are easier to type with a standard
474 /// keyboard layout, contrary to `Ofᐸᑊ_ᐳ`, which will probably require
475 /// copy-pasting.
476 #[doc(cfg(educational))]
477 pub trait Ofᐸᑊ_ᐳ = ForLt;
478 );
479
480 _ => (
481 mod r#trait {
482 #![allow(unused)]
483 pub use super::*;
484 macro_rules! __ {() => ()}
485 use __ as ForLt;
486 }
487
488 pub trait Ofᐸᑊ_ᐳ where Self : ForLt {}
489 impl<T : ?Sized> Ofᐸᑊ_ᐳ for T where Self : ForLt {}
490 );
491}
492
493/// <code>[ForFixed]\<T\></code> is a macro-free alias for
494/// <code>[ForLt!]\(\<\'_unused\> = T\)</code>.
495///
496/// To be used when the generic lifetime parameter is to be ignored, while
497/// calling into some HKT API.
498pub
499type ForFixed<T : Sized> = ForLt!(T);
500
501/// <code>[ForRef]\<T\></code> is a macro-free alias for
502/// <code>[ForLt!]\(\<\'any\> = \&\'any T\)</code>.
503pub
504type ForRef<T : ?Sized> = ForLt!(&'_ T);
505
506/// <code>[ForRefMut]\<T\></code> is a macro-free alias for
507/// <code>[ForLt!]\(\<\'any\> = \&\'any mut T\)</code>.
508pub
509type ForRefMut<T : ?Sized> = ForLt!(&'_ mut T);
510
511#[cfg(feature = "ui-tests")]
512#[doc = include_str!("compile_fail_tests.md")]
513mod _compile_fail_tests {}