use super::{super::super::func::ext::UnwrapValid, args::*}; pub trait TupleApply: Sized { type R; fn apply B>(self, r: RA, op: F) -> Self::R; } pub trait TupleMap: Sized { type R; fn map B>(self, op: F) -> Self::R; } pub trait TupleFold: Sized { fn fold A>(self, op: F) -> A; } impl TupleApply for (A, A) where RA: Tuple2, { type R = (B, B); fn apply B>(self, r: RA, op: F) -> Self::R { let (l, r) = (self, r.get()); (op(l.0, r.0), op(l.1, r.1)) } } impl TupleMap for (A, A) { type R = (B, B); fn map B>(self, op: F) -> Self::R { (op(self.0), op(self.1)) } } impl TupleFold for (A, A) { fn fold A>(self, op: F) -> A { op(self.0, self.1) } } impl TupleApply for (A, A, A) where RA: Tuple3, { type R = (B, B, B); fn apply B>(self, r: RA, op: F) -> Self::R { let (l, r) = (self, r.get()); (op(l.0, r.0), op(l.1, r.1), op(l.2, r.2)) } } impl TupleMap for (A, A, A) { type R = (B, B, B); fn map B>(self, op: F) -> Self::R { (op(self.0), op(self.1), op(self.2)) } } impl TupleFold for (A, A, A) { fn fold A>(self, op: F) -> A { op(op(self.0, self.1), self.2) } } impl TupleApply for (A, A, A, A) where RA: Tuple4, { type R = (B, B, B, B); fn apply B>(self, r: RA, op: F) -> Self::R { 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 TupleMap for (A, A, A, A) { type R = (B, B, B, B); fn map B>(self, op: F) -> Self::R { (op(self.0), op(self.1), op(self.2), op(self.3)) } } impl TupleFold for (A, A, A, A) { fn fold A>(self, op: F) -> A { op(op(op(self.0, self.1), self.2), self.3) } } impl TupleApply for [A; N] where RA: TupleA, { type R = [B; N]; fn apply B>(self, r: RA, op: F) -> Self::R { 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::>().try_into() else { unreachable!() }; b } } impl TupleMap for [A; N] { type R = [B; N]; fn map B>(self, op: F) -> Self::R { self.map(op) } } impl TupleFold for [A; N] { fn fold A>(self, op: F) -> A { let mut i = self.into_iter(); let h = i.next().valid(); i.fold(h, op) } }