1use core::convert::identity;
2
3pub trait Bifunctor<'a, A, B> {
11 type Target<T, U>;
12
13 fn bimap<C, D, L, R>(self, left: L, right: R) -> Self::Target<C, D>
16 where
17 L: Fn(A) -> C + 'a,
18 R: Fn(B) -> D + 'a;
19
20 fn lmap<C, L>(self, left: L) -> Self::Target<C, B>
22 where
23 Self: Sized,
24 B: 'a,
25 L: Fn(A) -> C + 'a,
26 {
27 self.bimap(left, identity)
28 }
29
30 fn rmap<D, R>(self, right: R) -> Self::Target<A, D>
32 where
33 Self: Sized,
34 A: 'a,
35 R: Fn(B) -> D + 'a,
36 {
37 self.bimap(identity, right)
38 }
39}
40
41impl<A, B> Bifunctor<'_, A, B> for Result<A, B> {
42 type Target<T, U> = Result<T, U>;
43
44 fn bimap<C, D, L, R>(self, left: L, right: R) -> Self::Target<C, D>
45 where
46 L: Fn(A) -> C,
47 R: Fn(B) -> D,
48 {
49 match self {
50 Ok(a) => Ok(left(a)),
51 Err(b) => Err(right(b)),
52 }
53 }
54}
55
56impl<A, B> Bifunctor<'_, A, B> for Vec<(A, B)> {
57 type Target<T, U> = Vec<(T, U)>;
58
59 fn bimap<C, D, L, R>(self, left: L, right: R) -> Self::Target<C, D>
60 where
61 L: Fn(A) -> C,
62 R: Fn(B) -> D,
63 {
64 self.into_iter().map(|(a, b)| (left(a), right(b))).collect()
65 }
66}