#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::optics::*,
classes::{
applicative::Applicative,
profunctor::{
Choice,
Profunctor,
Strong,
Wander,
wander::TraversalFunc,
},
},
impl_kind,
kinds::*,
},
fp_macros::*,
std::marker::PhantomData,
};
#[document_type_parameters(
"The lifetime of the values.",
"The underlying profunctor brand.",
"The index type.",
"The focus type.",
"The target focus type."
)]
pub struct Indexed<'a, P, I, A, B>
where
P: Profunctor,
I: 'a,
A: 'a,
B: 'a, {
pub inner: Apply!(<P as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, (I, A), B>),
}
#[document_type_parameters(
"The lifetime of the values.",
"The underlying profunctor brand.",
"The index type.",
"The focus type.",
"The target focus type."
)]
impl<'a, P, I, A, B> Indexed<'a, P, I, A, B>
where
P: Profunctor,
I: 'a,
A: 'a,
B: 'a,
{
#[document_signature]
#[document_parameters("The underlying profunctor value.")]
#[document_returns("A new `Indexed` instance.")]
#[document_examples]
pub fn new(
inner: Apply!(<P as Kind!( type Of<'b, T: 'b, U: 'b>: 'b; )>::Of<'a, (I, A), B>)
) -> Self {
Self {
inner,
}
}
}
impl_kind! {
impl<P: Profunctor + 'static, I: 'static> for IndexedBrand<P, I> {
#[document_default]
type Of<'a, A: 'a, B: 'a>: 'a = Indexed<'a, P, I, A, B>;
}
}
#[document_type_parameters("The underlying profunctor brand.", "The index type.")]
impl<P: Profunctor + 'static, I: 'static> Profunctor for IndexedBrand<P, I> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The new input type.",
"The original input type.",
"The original output type.",
"The new output type."
)]
#[document_parameters(
"The contravariant function to apply to the input.",
"The covariant function to apply to the output.",
"The indexed profunctor instance."
)]
#[document_returns("A transformed `Indexed` instance.")]
#[document_examples]
fn dimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
ab: impl Fn(A) -> B + 'a,
cd: impl Fn(C) -> D + 'a,
pbc: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, B, C>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, D>) {
Indexed::new(P::dimap(move |(i, a)| (i, ab(a)), cd, pbc.inner))
}
}
#[document_type_parameters("The underlying profunctor brand.", "The index type.")]
impl<P: Strong + 'static, I: 'static> Strong for IndexedBrand<P, I> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The input type of the profunctor.",
"The output type of the profunctor.",
"The type of the second component (threaded through unchanged)."
)]
#[document_parameters("The indexed profunctor instance to lift.")]
#[document_returns("A transformed `Indexed` instance that operates on pairs.")]
#[document_examples]
fn first<'a, A: 'a, B: 'a, C>(
pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (A, C), (B, C)>) {
Indexed::new(P::dimap(
|(i, (a, c))| ((i, a), c),
|(b, c)| (b, c),
P::first::<(I, A), B, C>(pab.inner),
))
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The input type of the profunctor.",
"The output type of the profunctor.",
"The type of the first component (threaded through unchanged)."
)]
#[document_parameters("The indexed profunctor instance to lift.")]
#[document_returns("A transformed `Indexed` instance that operates on pairs.")]
#[document_examples]
fn second<'a, A: 'a, B: 'a, C: 'a>(
pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, (C, A), (C, B)>) {
Indexed::new(P::dimap(
|(i, (c, a))| (c, (i, a)),
|(c, b)| (c, b),
P::second::<(I, A), B, C>(pab.inner),
))
}
}
#[document_type_parameters("The underlying profunctor brand.", "The index type.")]
impl<P: Choice + 'static, I: 'static> Choice for IndexedBrand<P, I> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The input type of the profunctor.",
"The output type of the profunctor.",
"The type of the alternative variant (threaded through unchanged)."
)]
#[document_parameters("The indexed profunctor instance to lift.")]
#[document_returns("A transformed `Indexed` instance that operates on `Result` types.")]
#[document_examples]
fn left<'a, A: 'a, B: 'a, C: 'a>(
pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<C, A>, Result<C, B>>)
{
Indexed::new(P::dimap(
|(i, r)| match r {
Err(a) => Err((i, a)),
Ok(c) => Ok(c),
},
|r| match r {
Err(b) => Err(b),
Ok(c) => Ok(c),
},
P::left::<(I, A), B, C>(pab.inner),
))
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The input type of the profunctor.",
"The output type of the profunctor.",
"The type of the alternative variant (threaded through unchanged)."
)]
#[document_parameters("The indexed profunctor instance to lift.")]
#[document_returns("A transformed `Indexed` instance that operates on `Result` types.")]
#[document_examples]
fn right<'a, A: 'a, B: 'a, C: 'a>(
pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, Result<A, C>, Result<B, C>>)
{
Indexed::new(P::dimap(
|(i, r)| match r {
Ok(a) => Ok((i, a)),
Err(c) => Err(c),
},
|r| match r {
Ok(b) => Ok(b),
Err(c) => Err(c),
},
P::right::<(I, A), B, C>(pab.inner),
))
}
}
#[document_type_parameters("The underlying profunctor brand.", "The index type.")]
impl<P: Wander + 'static, I: Clone + 'static> Wander for IndexedBrand<P, I> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The source type of the structure.",
"The target type of the structure.",
"The source type of the focus.",
"The target type of the focus."
)]
#[document_parameters("The traversal function.", "The indexed profunctor instance.")]
#[document_returns("A transformed `Indexed` instance that operates on structures.")]
#[document_examples]
fn wander<'a, S: 'a, T: 'a, A: 'a, B: 'a + Clone>(
traversal: impl TraversalFunc<'a, S, T, A, B> + 'a,
pab: Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, A, B>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a, U: 'a>: 'a; )>::Of<'a, S, T>) {
struct IWanderAdapter<'a, I, S, T, A, B, TFunc> {
traversal: TFunc,
_phantom: PhantomData<&'a (I, S, T, A, B)>,
}
impl<'a, I: Clone + 'a, S: 'a, T: 'a, A: 'a, B: 'a, TFunc>
TraversalFunc<'a, (I, S), T, (I, A), B> for IWanderAdapter<'a, I, S, T, A, B, TFunc>
where
TFunc: TraversalFunc<'a, S, T, A, B> + 'a,
{
fn apply<M: Applicative>(
&self,
f: Box<
dyn Fn((I, A)) -> Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, B>)
+ 'a,
>,
(i, s): (I, S),
) -> Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, T>)
where
Apply!(<M as Kind!( type Of<'c, U: 'c>: 'c; )>::Of<'a, B>): Clone, {
let i_clone = i.clone();
self.traversal.apply::<M>(Box::new(move |a| f((i_clone.clone(), a))), s)
}
}
Indexed::new(P::wander(
IWanderAdapter {
traversal,
_phantom: PhantomData,
},
pab.inner,
))
}
}
}
pub use inner::*;