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
#![feature(fn_traits, unboxed_closures)]
#![feature(const_fn)]
#![feature(const_generics)]
#![feature(unsized_locals)]
#![feature(trivial_bounds)]
#![allow(incomplete_features)]

use std::marker::PhantomData;
use tuple_list::{Tuple, TupleList};

pub trait Monoid<N> {
     fn identity() -> Self;
    fn operator(first: Self, second: Self) -> Self;
}

pub trait RepeatedOperation<T, N> {
    fn operation(self) -> T;
}

impl<T, N> RepeatedOperation<T, N> for ()
where
    T: Monoid<N>,
{
    #[inline(always)]
    fn operation(self) -> T {
        T::identity()
    }
}

impl<T, R, N> RepeatedOperation<T, N> for (T, R)
where
    T: Monoid<N>,
    R: RepeatedOperation<T, N>,
    Self: TupleList,
{
    #[inline(always)]
    fn operation(self) -> T {
        Monoid::operator(self.0, self.1.operation())
    }
}

pub struct VariFunc<T:  ?Sized, N:  ?Sized> {
    a: PhantomData<T>,
    b: PhantomData<N>,
}

impl<I, T, N> FnOnce<I> for VariFunc<T, N>
where
    I: tuple_list::Tuple,
    <I as Tuple>::TupleList: RepeatedOperation<T, N>,
{
    type Output = T;
    #[inline(always)]
    extern "rust-call" fn call_once(self, args: I) -> T {
        RepeatedOperation::operation(Tuple::into_tuple_list(args))
    }
}

pub const fn gen_function<T: ?Sized+ PartialEq+ Eq, N>() -> VariFunc<T, N> {
    VariFunc::<T, N> { a: PhantomData, b: PhantomData }
}