#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::ConstBrand,
classes::{
apply_first::ApplyFirst,
apply_second::ApplySecond,
clone_fn::CloneFn,
functor::Functor,
lift::Lift,
monoid::Monoid,
pointed::Pointed,
semiapplicative::Semiapplicative,
semigroup::Semigroup,
},
impl_kind,
kinds::*,
},
fp_macros::*,
std::marker::PhantomData,
};
#[document_type_parameters(
"The lifetime of the values.",
"The stored type.",
"The ignored type."
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Const<'a, R, A>(pub R, pub PhantomData<&'a A>);
#[document_type_parameters(
"The lifetime of the values.",
"The stored type.",
"The ignored type."
)]
#[document_parameters("The `Const` instance.")]
impl<'a, R, A> Const<'a, R, A> {
#[document_signature]
#[document_parameters("The value to store.")]
#[document_returns("A new `Const` instance.")]
#[document_examples]
pub fn new(r: R) -> Self {
Const(r, PhantomData)
}
#[document_signature]
#[document_type_parameters("The new phantom type.")]
#[document_parameters("The function to map (ignored).")]
#[document_returns(
"A new `Const` instance with the same stored value but a different phantom type."
)]
#[document_examples]
pub fn map<B>(
self,
_f: impl FnOnce(A) -> B,
) -> Const<'a, R, B> {
Const::new(self.0)
}
#[document_signature]
#[document_type_parameters("The second phantom type.", "The result phantom type.")]
#[document_parameters("The other `Const` instance.", "The function to lift (ignored).")]
#[document_returns("A new `Const` instance with the appended stored values.")]
#[document_examples]
pub fn lift2<B, C>(
self,
other: Const<'a, R, B>,
_f: impl FnOnce(A, B) -> C,
) -> Const<'a, R, C>
where
R: Semigroup, {
Const::new(R::append(self.0, other.0))
}
#[document_signature]
#[document_type_parameters("The phantom type of the second `Const` instance.")]
#[document_parameters("The second `Const` instance.")]
#[document_returns("A new `Const` instance with the appended stored values.")]
#[document_examples]
pub fn apply_first<B>(
self,
other: Const<'a, R, B>,
) -> Const<'a, R, A>
where
R: Semigroup, {
Const::new(R::append(self.0, other.0))
}
#[document_signature]
#[document_type_parameters("The phantom type of the second `Const` instance.")]
#[document_parameters("The second `Const` instance.")]
#[document_returns("A new `Const` instance with the appended stored values.")]
#[document_examples]
pub fn apply_second<B>(
self,
other: Const<'a, R, B>,
) -> Const<'a, R, B>
where
R: Semigroup, {
Const::new(R::append(self.0, other.0))
}
#[document_signature]
#[document_parameters("The value to wrap (ignored).")]
#[document_returns("A new `Const` instance with the empty value of the stored type.")]
#[document_examples]
pub fn pure(_a: A) -> Self
where
R: Monoid, {
Const::new(R::empty())
}
}
impl_kind! {
impl<R: 'static> for ConstBrand<R> {
type Of<'a, A: 'a>: 'a = Const<'a, R, A>;
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static> Functor for ConstBrand<R> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The function to map (ignored).",
"The `Const` instance to map over."
)]
#[document_returns("A new `Const` instance with the same stored value.")]
#[document_examples]
fn map<'a, A: 'a, B: 'a>(
_f: impl Fn(A) -> B + 'a,
fa: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>) {
fa.map(_f)
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static + Semigroup> Lift for ConstBrand<R> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The first input type.",
"The second input type.",
"The output type."
)]
#[document_parameters(
"The function to lift (ignored).",
"The first `Const` instance.",
"The second `Const` instance."
)]
#[document_returns("A new `Const` instance with the combined stored values.")]
#[document_examples]
fn lift2<'a, A, B, C>(
_func: impl Fn(A, B) -> C + 'a,
fa: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>),
fb: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>),
) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, C>)
where
A: Clone + 'a,
B: Clone + 'a,
C: 'a, {
fa.lift2(fb, _func)
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static + Semigroup> Semiapplicative for ConstBrand<R> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The function brand.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The `Const` instance containing a function.",
"The `Const` instance containing a value."
)]
#[document_returns("A new `Const` instance with the combined stored values.")]
#[document_examples]
fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
ff: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
fa: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>) {
Const::new(R::append(ff.0, fa.0))
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static + Semigroup> ApplyFirst for ConstBrand<R> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The first type.",
"The second type."
)]
#[document_parameters("The first `Const` instance.", "The second `Const` instance.")]
#[document_returns("A new `Const` instance with the combined stored values.")]
#[document_examples]
fn apply_first<'a, A: 'a, B: 'a>(
fa: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>),
fb: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>),
) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>) {
fa.apply_first(fb)
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static + Semigroup> ApplySecond for ConstBrand<R> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The first type.",
"The second type."
)]
#[document_parameters("The first `Const` instance.", "The second `Const` instance.")]
#[document_returns("A new `Const` instance with the combined stored values.")]
#[document_examples]
fn apply_second<'a, A: 'a, B: 'a>(
fa: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>),
fb: Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>),
) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, B>) {
fa.apply_second(fb)
}
}
#[document_type_parameters("The stored type.")]
impl<R: 'static + Monoid> Pointed for ConstBrand<R> {
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type to wrap (ignored).")]
#[document_parameters("The value to wrap (ignored).")]
#[document_returns("A new `Const` instance with the empty value of the stored type.")]
#[document_examples]
fn pure<'a, A: 'a>(_a: A) -> Apply!(<Self as Kind!( type Of<'b, T: 'b>: 'b; )>::Of<'a, A>) {
Const::pure(_a)
}
}
}
pub use inner::*;
impl<'a, R: Clone, A> Clone for Const<'a, R, A> {
fn clone(&self) -> Self {
Const(self.0.clone(), std::marker::PhantomData)
}
}
impl<'a, R: Copy, A> Copy for Const<'a, R, A> {}