#![allow(clippy::module_inception)]
use crate::{Cons, HList, Nil};
use super::{MapFn, Mapper};
pub trait Map<Mapper>: HList {
type Output: HList;
fn map(self, mapper: Mapper) -> Self::Output;
}
impl<M> Map<M> for Nil {
type Output = Nil;
fn map(self, _: M) -> Self::Output {
self
}
}
impl<M, R, Head, Tail> Map<M> for Cons<Head, Tail>
where
M: FnMut(Head) -> R,
Tail: Map<M>,
{
type Output = Cons<R, Tail::Output>;
fn map(self, mut mapper: M) -> Self::Output {
let Cons(head, tail) = self;
let head = mapper(head);
let tail = tail.map(mapper);
Cons(head, tail)
}
}
impl<MHead, MTail, Head, Tail, R> Map<Cons<MHead, MTail>> for Cons<Head, Tail>
where
MHead: FnOnce(Head) -> R,
Tail: Map<MTail>,
{
type Output = Cons<R, Tail::Output>;
fn map(self, mapper: Cons<MHead, MTail>) -> Self::Output {
let Cons(head, tail) = self;
let Cons(mapper_head, mapper_tail) = mapper;
let head = mapper_head(head);
let tail = tail.map(mapper_tail);
Cons(head, tail)
}
}
impl<M, Head, Tail> Map<Mapper<M>> for Cons<Head, Tail>
where
M: MapFn<Head>,
Tail: Map<Mapper<M>>,
{
type Output = Cons<M::Output, Tail::Output>;
fn map(self, mut mapper: Mapper<M>) -> Self::Output {
let Cons(head, tail) = self;
let head = mapper.map(head);
let tail = tail.map(mapper);
Cons(head, tail)
}
}