use core::marker::PhantomData;
use core::ops::Deref;
use curry2::Curry2;
use curry3::Curry3;
use self::compose::Compose;
pub mod compose;
pub mod curry2;
pub mod curry3;
pub fn tuple2<A, B>(a: A, b: B) -> (A, B) {
(a, b)
}
pub fn tuple3<A, B, C>(a: A, b: B, c: C) -> (A, B, C) {
(a, b, c)
}
pub(self) mod arg {
#[allow(unreachable_pub)]
pub trait Arg {
type T;
}
}
#[derive(Clone, Copy)]
pub struct Just<T>( pub T);
pub struct Nothing<T>(pub(self) PhantomData<T>);
impl<T> Nothing<T> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<T> Default for Nothing<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Clone for Nothing<T> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<T> arg::Arg for Just<T> {
type T = T;
}
impl<T> arg::Arg for Nothing<T> {
type T = T;
}
#[allow(non_camel_case_types)]
pub type call_deref<F, A, B> = fn(f: F, a: A) -> B;
pub fn call_deref<F, A, ADeref: ?Sized, B>(f: F, a: A) -> B
where A: Deref<Target = ADeref>,
F: for<'a> F1Once<&'a ADeref, Ret = B>
{
f.call1(a.deref())
}
pub trait F1Once<A> {
type Ret;
fn call1(self, a: A) -> Self::Ret;
fn chain<G, C>(self, g: G) -> Compose<Self, G, Self::Ret>
where Self: Sized,
G: F1Once<Self::Ret, Ret = C>
{
Compose::compose(self, g)
}
fn chain_ref<G, BDeref: ?Sized, C>(
self,
g: G)
-> Compose<Self, curry2::Applied1<call_deref<G, Self::Ret, C>, G, Self::Ret, C>, Self::Ret>
where Self: Sized,
G: for<'any> F1Once<&'any BDeref, Ret = C>,
Self::Ret: Deref<Target = BDeref>
{
Compose::compose(self,
(call_deref as call_deref<G, Self::Ret, C>).curry().call(g))
}
}
pub trait F2Once<A, B>: Sized {
type Ret;
type Curried;
fn call1(self, a: A, b: B) -> Self::Ret;
fn curry(self) -> Self::Curried;
}
pub trait F3Once<A, B, C>: Sized {
type Ret;
type Curried;
fn call1(self, a: A, b: B, c: C) -> Self::Ret;
fn curry(self) -> Self::Curried;
}
pub trait F1<A>: F1Once<A> {
fn call(&self, a: A) -> Self::Ret;
}
pub trait F2<A, B>: F2Once<A, B> {
fn call(&self, a: A, b: B) -> Self::Ret;
}
pub trait F3<A, B, C>: F3Once<A, B, C> {
fn call(&self, a: A, b: B, c: C) -> Self::Ret;
}
impl<F, A, B> F1<A> for F where F: Fn(A) -> B
{
fn call(&self, a: A) -> B {
self(a)
}
}
impl<F, A, B> F1Once<A> for F where F: FnOnce(A) -> B
{
type Ret = B;
fn call1(self, a: A) -> B {
self(a)
}
}
impl<F, A, B, C> F2<A, B> for F where F: Fn(A, B) -> C
{
fn call(&self, a: A, b: B) -> Self::Ret {
self(a, b)
}
}
impl<F, A, B, C> F2Once<A, B> for F where F: FnOnce(A, B) -> C
{
type Ret = C;
type Curried = curry2::Applied0<Self, A, B, C>;
fn call1(self, a: A, b: B) -> C {
self(a, b)
}
fn curry(self) -> Self::Curried {
Curry2::curry(self)
}
}
impl<F, A, B, C, D> F3<A, B, C> for F where F: Fn(A, B, C) -> D
{
fn call(&self, a: A, b: B, c: C) -> D {
self(a, b, c)
}
}
impl<F, A, B, C, D> F3Once<A, B, C> for F where F: FnOnce(A, B, C) -> D
{
type Ret = D;
type Curried = curry3::Applied0<Self, A, B, C, D>;
fn call1(self, a: A, b: B, c: C) -> D {
self(a, b, c)
}
fn curry(self) -> Self::Curried {
Curry3::curry(self)
}
}