higher_cat/
functor.rs

1use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
2use std::hash::{BuildHasher, Hash};
3
4use higher::Lift;
5
6/// A `Functor` lets you change the type parameter of a generic type.
7///
8/// A `Functor` defines a method `map` on a type `F<_>: Functor` which converts
9/// an `F<A>` to `F<B>` using a function `Fn(A) -> B` applied to the `A`s inside
10/// it.
11///
12/// You can also use this just to modify the values inside your container value
13/// without changing their type, if the mapping function returns a value of the
14/// same type.  This is called an "endofunctor."
15pub trait Functor<A, B>: Lift<A, B> {
16    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
17    where
18        F: Fn(A) -> B;
19}
20
21impl<A, B> Functor<A, B> for Option<A> {
22    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
23    where
24        F: Fn(A) -> B,
25    {
26        self.map(f)
27    }
28}
29
30impl<A, B, E> Functor<A, B> for Result<A, E> {
31    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
32    where
33        F: Fn(A) -> B,
34    {
35        self.map(f)
36    }
37}
38
39impl<A, B> Functor<A, B> for Vec<A> {
40    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
41    where
42        F: Fn(A) -> B,
43    {
44        self.into_iter().map(f).collect()
45    }
46}
47
48impl<A, B, S> Functor<A, B> for HashSet<A, S>
49where
50    A: Hash + Eq,
51    B: Hash + Eq,
52    S: BuildHasher + Default,
53{
54    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
55    where
56        F: Fn(A) -> B,
57    {
58        self.into_iter().map(f).collect()
59    }
60}
61
62impl<A, B> Functor<A, B> for BTreeSet<A>
63where
64    A: Ord,
65    B: Ord,
66{
67    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
68    where
69        F: Fn(A) -> B,
70    {
71        self.into_iter().map(f).collect()
72    }
73}
74
75impl<A, B, C, D, S> Functor<(A, B), (C, D)> for HashMap<A, B, S>
76where
77    A: Hash + Eq,
78    B: Hash + Eq,
79    C: Hash + Eq,
80    D: Hash + Eq,
81    S: BuildHasher + Default,
82{
83    fn map<F>(self, f: F) -> <Self as Lift<(A, B), (C, D)>>::Target1
84    where
85        F: Fn((A, B)) -> (C, D),
86    {
87        self.into_iter().map(f).collect()
88    }
89}
90
91impl<A, B, C, D> Functor<(A, B), (C, D)> for BTreeMap<A, B>
92where
93    A: Ord,
94    B: Ord,
95    C: Ord,
96    D: Ord,
97{
98    fn map<F>(self, f: F) -> <Self as Lift<(A, B), (C, D)>>::Target1
99    where
100        F: Fn((A, B)) -> (C, D),
101    {
102        self.into_iter().map(f).collect()
103    }
104}
105
106impl<A, B> Functor<A, B> for VecDeque<A> {
107    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
108    where
109        F: Fn(A) -> B,
110    {
111        self.into_iter().map(f).collect()
112    }
113}
114
115impl<A, B> Functor<A, B> for LinkedList<A> {
116    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
117    where
118        F: Fn(A) -> B,
119    {
120        self.into_iter().map(f).collect()
121    }
122}
123
124impl<A, B> Functor<A, B> for BinaryHeap<A>
125where
126    A: Ord,
127    B: Ord,
128{
129    fn map<F>(self, f: F) -> <Self as Lift<A, B>>::Target1
130    where
131        F: Fn(A) -> B,
132    {
133        self.into_iter().map(f).collect()
134    }
135}