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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#![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 }
}