use core::marker::PhantomData;
use super::arg::Arg;
use super::{F1Once, F2Once, Just, Nothing, F1};
pub type Applied0<F, A, B, C> = Curry2<F, Nothing<A>, Nothing<B>, C>;
pub type Applied1<F, A, B, C> = Curry2<F, Just<A>, Nothing<B>, C>;
pub struct Curry2<F, A, B, C> {
f: F,
a: A,
_s: PhantomData<(B, C)>,
}
impl<A, B, C, F> Clone for Curry2<F, A, B, C>
where A: Arg + Clone,
B: Arg,
F: Clone + Fn(A::T, B::T) -> C
{
fn clone(&self) -> Self {
Curry2 { f: self.f.clone(),
a: self.a.clone(),
_s: PhantomData }
}
}
impl<A, B, C, F> Copy for Curry2<F, A, B, C>
where A: Arg + Copy,
B: Arg,
F: Copy + Fn(A::T, B::T) -> C
{
}
impl<F, A, B, C> Applied0<F, A, B, C> where F: F2Once<A, B, Ret = C>
{
pub fn curry(f: F) -> Self {
Self { f,
a: Nothing::new(),
_s: PhantomData }
}
pub fn uncurry(self) -> F {
self.f
}
}
impl<F, A, B, C> F1<A> for Applied0<F, A, B, C> where F: Clone + Fn(A, B) -> C
{
fn call(&self, a: A) -> Applied1<F, A, B, C> {
Applied1::<F, A, B, C> { a: Just(a),
f: self.f.clone(),
_s: PhantomData }
}
}
impl<F, A, B, C> F1Once<A> for Applied0<F, A, B, C> where F: FnOnce(A, B) -> C
{
type Ret = Applied1<F, A, B, C>;
fn call1(self, a: A) -> Applied1<F, A, B, C> {
Applied1::<F, A, B, C> { a: Just(a),
f: self.f,
_s: PhantomData }
}
}
impl<F, A, B, C> F1<B> for Applied1<F, A, B, C>
where F: Fn(A, B) -> C,
A: Clone
{
fn call(&self, b: B) -> C {
(self.f)(self.a.0.clone(), b)
}
}
impl<F, A, B, C> F1Once<B> for Applied1<F, A, B, C> where F: FnOnce(A, B) -> C
{
type Ret = C;
fn call1(self, b: B) -> C {
(self.f)(self.a.0, b)
}
}