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
94
95
96
97
98
99
100
101
102
103
104
105
106
use super::{super::super::func::ext::UnwrapValid, args::*};

pub trait TupleApply<RA, A>: Sized {
	type R<B>;
	fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B>;
}
pub trait TupleMap<A>: Sized {
	type R<B>;
	fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B>;
}
pub trait TupleFold<A>: Sized {
	fn fold<F: Fn(A, A) -> A>(self, op: F) -> A;
}

impl<RA, A> TupleApply<RA, A> for (A, A)
where
	RA: Tuple2<A>,
{
	type R<B> = (B, B);
	fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
		let (l, r) = (self, r.get());
		(op(l.0, r.0), op(l.1, r.1))
	}
}
impl<A> TupleMap<A> for (A, A) {
	type R<B> = (B, B);
	fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
		(op(self.0), op(self.1))
	}
}
impl<A> TupleFold<A> for (A, A) {
	fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
		op(self.0, self.1)
	}
}

impl<RA, A> TupleApply<RA, A> for (A, A, A)
where
	RA: Tuple3<A>,
{
	type R<B> = (B, B, B);
	fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
		let (l, r) = (self, r.get());
		(op(l.0, r.0), op(l.1, r.1), op(l.2, r.2))
	}
}
impl<A> TupleMap<A> for (A, A, A) {
	type R<B> = (B, B, B);
	fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
		(op(self.0), op(self.1), op(self.2))
	}
}
impl<A> TupleFold<A> for (A, A, A) {
	fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
		op(op(self.0, self.1), self.2)
	}
}

impl<RA, A> TupleApply<RA, A> for (A, A, A, A)
where
	RA: Tuple4<A>,
{
	type R<B> = (B, B, B, B);
	fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
		let (l, r) = (self, r.get());
		(op(l.0, r.0), op(l.1, r.1), op(l.2, r.2), op(l.3, r.3))
	}
}
impl<A> TupleMap<A> for (A, A, A, A) {
	type R<B> = (B, B, B, B);
	fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
		(op(self.0), op(self.1), op(self.2), op(self.3))
	}
}
impl<A> TupleFold<A> for (A, A, A, A) {
	fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
		op(op(op(self.0, self.1), self.2), self.3)
	}
}

impl<RA, A, const N: usize> TupleApply<RA, A> for [A; N]
where
	RA: TupleA<A, N>,
{
	type R<B> = [B; N];
	fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
		let (l, r) = (self, r.get()); // TODO zip array stabilization
		let Ok(b) = l.into_iter().zip(r).map(|(l, r)| op(l, r)).collect::<Vec<_>>().try_into() else {
			unreachable!()
		};
		b
	}
}
impl<A, const N: usize> TupleMap<A> for [A; N] {
	type R<B> = [B; N];
	fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
		self.map(op)
	}
}
impl<A, const N: usize> TupleFold<A> for [A; N] {
	fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
		let mut i = self.into_iter();
		let h = i.next().valid();
		i.fold(h, op)
	}
}