|
1 | 1 | package fj; |
2 | 2 |
|
3 | | -import fj.data.List; |
4 | | -import fj.data.Stream; |
5 | | -import fj.data.Array; |
6 | | -import java.lang.ref.SoftReference; |
7 | 3 |
|
8 | 4 | /** |
9 | 5 | * A product-1. Also, the identity monad. |
10 | 6 | * |
11 | 7 | * @version %build.number% |
12 | 8 | */ |
13 | | -public abstract class P1<A> { |
| 9 | +public interface P1<A> { |
14 | 10 | /** |
15 | 11 | * Access the first element of the product. |
16 | 12 | * |
17 | 13 | * @return The first element of the product. |
18 | 14 | */ |
19 | 15 | public abstract A _1(); |
20 | | - |
21 | | - /** |
22 | | - * Map the element of the product. |
23 | | - * |
24 | | - * @param f The function to map with. |
25 | | - * @return A product with the given function applied. |
26 | | - */ |
27 | | - public final <X> P1<X> map(final F<A, X> f) { |
28 | | - return new P1<X>() { |
29 | | - public X _1() { |
30 | | - return f.f(P1.this._1()); |
31 | | - } |
32 | | - }; |
33 | | - } |
34 | | - |
35 | | - /** |
36 | | - * Returns a function that returns the first element of a product. |
37 | | - * |
38 | | - * @return A function that returns the first element of a product. |
39 | | - */ |
40 | | - public static <A> F<P1<A>, A> __1() { |
41 | | - return new F<P1<A>, A>() { |
42 | | - public A f(final P1<A> p) { |
43 | | - return p._1(); |
44 | | - } |
45 | | - }; |
46 | | - } |
47 | | - |
48 | | - /** |
49 | | - * Promote any function to a transformation between P1s. |
50 | | - * |
51 | | - * @param f A function to promote to a transformation between P1s. |
52 | | - * @return A function promoted to operate on P1s. |
53 | | - */ |
54 | | - public static <A, B> F<P1<A>, P1<B>> fmap(final F<A, B> f) { |
55 | | - return new F<P1<A>, P1<B>>() { |
56 | | - public P1<B> f(final P1<A> a) { |
57 | | - return a.map(f); |
58 | | - } |
59 | | - }; |
60 | | - } |
61 | | - |
62 | | - /** |
63 | | - * Binds the given function to the value in a product-1 with a final join. |
64 | | - * |
65 | | - * @param a A value in a product-1 to which to apply a function. |
66 | | - * @param f A function to apply to the value in a product-1. |
67 | | - * @return The result of applying the given function to the value of given product-1. |
68 | | - */ |
69 | | - public static <A, B> P1<B> bind(final P1<A> a, final F<A, P1<B>> f) { |
70 | | - return new P1<B>() { |
71 | | - public B _1() { |
72 | | - return f.f(a._1())._1(); |
73 | | - } |
74 | | - }; |
75 | | - } |
76 | | - |
77 | | - /** |
78 | | - * Promotes the given function so that it returns its value in a P1. |
79 | | - * |
80 | | - * @param f A function to have its result wrapped in a P1. |
81 | | - * @return A function whose result is wrapped in a P1. |
82 | | - */ |
83 | | - public static <A, B> F<A, P1<B>> curry(final F<A, B> f) { |
84 | | - return new F<A, P1<B>>() { |
85 | | - public P1<B> f(final A a) { |
86 | | - return new P1<B>() { |
87 | | - public B _1() { |
88 | | - return f.f(a); |
89 | | - } |
90 | | - }; |
91 | | - } |
92 | | - }; |
93 | | - } |
94 | | - |
95 | | - /** |
96 | | - * Performs function application within a P1 (applicative functor pattern). |
97 | | - * |
98 | | - * @param ca The P1 to which to apply a function. |
99 | | - * @param cf The P1 function to apply. |
100 | | - * @return A new P1 after applying the given P1 function to the first argument. |
101 | | - */ |
102 | | - public static <A, B> P1<B> apply(final P1<A> ca, final P1<F<A, B>> cf) { |
103 | | - return bind(cf, new F<F<A, B>, P1<B>>() { |
104 | | - public P1<B> f(final F<A, B> f) { |
105 | | - return fmap(f).f(ca); |
106 | | - } |
107 | | - }); |
108 | | - } |
109 | | - |
110 | | - /** |
111 | | - * Binds the given function to the values in the given P1s with a final join. |
112 | | - * |
113 | | - * @param ca A given P1 to bind the given function with. |
114 | | - * @param cb A given P1 to bind the given function with. |
115 | | - * @param f The function to apply to the values in the given P1s. |
116 | | - * @return A new P1 after performing the map, then final join. |
117 | | - */ |
118 | | - public static <A, B, C> P1<C> bind(final P1<A> ca, final P1<B> cb, final F<A, F<B, C>> f) { |
119 | | - return apply(cb, fmap(f).f(ca)); |
120 | | - } |
121 | | - |
122 | | - /** |
123 | | - * Joins a P1 of a P1 with a bind operation. |
124 | | - * |
125 | | - * @param a The P1 of a P1 to join. |
126 | | - * @return A new P1 that is the join of the given P1. |
127 | | - */ |
128 | | - public static <A> P1<A> join(final P1<P1<A>> a) { |
129 | | - return bind(a, Function.<P1<A>>identity()); |
130 | | - } |
131 | | - |
132 | | - /** |
133 | | - * Promotes a function of arity-2 to a function on P1s. |
134 | | - * |
135 | | - * @param f The function to promote. |
136 | | - * @return A function of arity-2 promoted to map over P1s. |
137 | | - */ |
138 | | - public static <A, B, C> F<P1<A>, F<P1<B>, P1<C>>> liftM2(final F<A, F<B, C>> f) { |
139 | | - return Function.curry(new F2<P1<A>, P1<B>, P1<C>>() { |
140 | | - public P1<C> f(final P1<A> pa, final P1<B> pb) { |
141 | | - return bind(pa, pb, f); |
142 | | - } |
143 | | - }); |
144 | | - } |
145 | | - |
146 | | - /** |
147 | | - * Turns a List of P1s into a single P1 of a List. |
148 | | - * |
149 | | - * @param as The list of P1s to transform. |
150 | | - * @return A single P1 for the given List. |
151 | | - */ |
152 | | - public static <A> P1<List<A>> sequence(final List<P1<A>> as) { |
153 | | - return as.foldRight(liftM2(List.<A>cons()), P.p(List.<A>nil())); |
154 | | - } |
155 | | - |
156 | | - /** |
157 | | - * A first-class version of the sequence method for lists of P1s. |
158 | | - * |
159 | | - * @return A function from a List of P1s to a single P1 of a List. |
160 | | - */ |
161 | | - public static <A> F<List<P1<A>>, P1<List<A>>> sequenceList() { |
162 | | - return new F<List<P1<A>>, P1<List<A>>>() { |
163 | | - public P1<List<A>> f(final List<P1<A>> as) { |
164 | | - return sequence(as); |
165 | | - } |
166 | | - }; |
167 | | - } |
168 | | - |
169 | | - /** |
170 | | - * Turns a stream of P1s into a single P1 of a stream. |
171 | | - * |
172 | | - * @param as The stream of P1s to transform. |
173 | | - * @return A single P1 for the given stream. |
174 | | - */ |
175 | | - public static <A> P1<Stream<A>> sequence(final Stream<P1<A>> as) { |
176 | | - return as.foldRight(liftM2(Stream.<A>cons()), P.p(Stream.<A>nil())); |
177 | | - } |
178 | | - |
179 | | - /** |
180 | | - * Turns an array of P1s into a single P1 of an array. |
181 | | - * |
182 | | - * @param as The array of P1s to transform. |
183 | | - * @return A single P1 for the given array. |
184 | | - */ |
185 | | - public static <A> P1<Array<A>> sequence(final Array<P1<A>> as) { |
186 | | - return new P1<Array<A>>() { |
187 | | - public Array<A> _1() { |
188 | | - return as.map(P1.<A>__1()); |
189 | | - } |
190 | | - }; |
191 | | - } |
192 | | - |
193 | | - /** |
194 | | - * Provides a memoising P1 that remembers its value. |
195 | | - * |
196 | | - * @return A P1 that calls this P1 once and remembers the value for subsequent calls. |
197 | | - */ |
198 | | - public final P1<A> memo() { |
199 | | - final P1<A> self = this; |
200 | | - return new P1<A>() { |
201 | | - private final Object latch = new Object(); |
202 | | - @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) |
203 | | - private volatile SoftReference<A> v; |
204 | | - |
205 | | - public A _1() { |
206 | | - A a = v != null ? v.get() : null; |
207 | | - if (a == null) |
208 | | - synchronized (latch) { |
209 | | - if (v == null || v.get() == null) |
210 | | - a = self._1(); |
211 | | - v = new SoftReference<A>(a); |
212 | | - } |
213 | | - return a; |
214 | | - } |
215 | | - }; |
216 | | - } |
217 | | - |
218 | | - /** |
219 | | - * Returns a constant function that always uses this value. |
220 | | - * |
221 | | - * @return A constant function that always uses this value. |
222 | | - */ |
223 | | - public final <B> F<B, A> constant() { |
224 | | - return new F<B, A>() { |
225 | | - public A f(final B b) { |
226 | | - return _1(); |
227 | | - } |
228 | | - }; |
229 | | - } |
230 | 16 | } |
0 commit comments