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
use std::marker::{Tuple, PhantomData};
use tupleops::{TuplePrepend, Prepend, TupleConcat, ConcatTuples};
use crate::Curried;
/// A trait for things which may be curried.
///
/// C is the rightmost argument being applied in the curry.
///
/// X is the rest of the arguments left over after currying.
///
/// This trait is automatically implemented for anything implementing [FnOnce](FnOnce) which takes one or more argument.
///
/// ```rust
/// use currying::*;
///
/// let f = |x, y, z| x + y + z;
/// let (x, y, z) = (1, 2, 3);
///
/// let fz = f.rcurry(z);
///
/// assert_eq!(fz(x, y), f(x, y, z));
///
/// let fyz = fz.rcurry(y);
///
/// assert_eq!(fyz(x), f(x, y, z));
///
/// let fxyz = fyz.rcurry(x);
///
/// assert_eq!(fxyz(), f(x, y, z));
/// ```
#[const_trait]
pub trait RCurry<C, X>
{
type Output;
fn rcurry(self, arg: C) -> Self::Output;
}
impl<C, X, F> const RCurry<C, X> for F
where
(C,): Tuple,
X: Tuple,
((), X): TupleConcat<(), X>,
ConcatTuples<(), X>: Tuple,
(ConcatTuples<(), X>, (C,)): TupleConcat<ConcatTuples<(), X>, (C,)>,
ConcatTuples<ConcatTuples<(), X>, (C,)>: Tuple,
F: FnOnce<ConcatTuples<ConcatTuples<(), X>, (C,)>>
{
type Output = Curried<(), X, (C,), F>;
fn rcurry(self, arg: C) -> Self::Output
{
Curried {
args_left: (),
args_right: (arg,),
func: self,
phantom: PhantomData
}
}
}