Skip to main content

fp_library/classes/
ref_pointed.rs

1//! Contexts that can be initialized from a reference via the [`ref_pure`] operation.
2//!
3//! Unlike [`Pointed::pure`](crate::classes::Pointed::pure), which takes ownership of
4//! the value, `ref_pure` accepts a reference and clones the value to produce the
5//! context. This enables by-reference generic code to construct contexts without
6//! requiring ownership.
7//!
8//! ### Examples
9//!
10//! ```
11//! use fp_library::{
12//! 	brands::*,
13//! 	classes::*,
14//! 	types::*,
15//! };
16//!
17//! let value = 42;
18//! let lazy = LazyBrand::<RcLazyConfig>::ref_pure(&value);
19//! assert_eq!(*lazy.evaluate(), 42);
20//! ```
21
22#[fp_macros::document_module]
23mod inner {
24	use {
25		crate::kinds::*,
26		fp_macros::*,
27	};
28
29	/// A type class for contexts that can be initialized from a reference.
30	///
31	/// The `Clone` bound on `A` is required because constructing an owned
32	/// `Of<A>` from `&A` inherently requires cloning. This is the only
33	/// by-reference trait with a `Clone` bound; all other by-ref traits
34	/// pass `&A` to a user-supplied closure, letting the user control
35	/// whether cloning happens.
36	#[kind(type Of<'a, A: 'a>: 'a;)]
37	pub trait RefPointed {
38		/// Wraps a cloned value in the context.
39		#[document_signature]
40		///
41		#[document_type_parameters(
42			"The lifetime of the value.",
43			"The type of the value to wrap. Must be `Clone`."
44		)]
45		///
46		#[document_parameters("A reference to the value to wrap.")]
47		///
48		#[document_returns("A new context containing a clone of the value.")]
49		#[document_examples]
50		///
51		/// ```
52		/// use fp_library::{
53		/// 	brands::*,
54		/// 	classes::*,
55		/// 	types::*,
56		/// };
57		///
58		/// let value = 42;
59		/// let lazy = LazyBrand::<RcLazyConfig>::ref_pure(&value);
60		/// assert_eq!(*lazy.evaluate(), 42);
61		/// ```
62		fn ref_pure<'a, A: Clone + 'a>(
63			a: &A
64		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>);
65	}
66
67	/// Wraps a cloned value in the context.
68	///
69	/// Free function version that dispatches to [the type class' associated function][`RefPointed::ref_pure`].
70	#[document_signature]
71	///
72	#[document_type_parameters(
73		"The lifetime of the value.",
74		"The brand of the context.",
75		"The type of the value to wrap. Must be `Clone`."
76	)]
77	///
78	#[document_parameters("A reference to the value to wrap.")]
79	///
80	#[document_returns("A new context containing a clone of the value.")]
81	#[document_examples]
82	///
83	/// ```
84	/// use fp_library::{
85	/// 	brands::*,
86	/// 	functions::*,
87	/// 	types::*,
88	/// };
89	///
90	/// let value = 42;
91	/// let lazy = ref_pure::<LazyBrand<RcLazyConfig>, _>(&value);
92	/// assert_eq!(*lazy.evaluate(), 42);
93	/// ```
94	pub fn ref_pure<'a, Brand: RefPointed, A: Clone + 'a>(
95		a: &A
96	) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
97		Brand::ref_pure(a)
98	}
99}
100
101pub use inner::*;