forked from functionaljava/functionaljava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDList.java
More file actions
131 lines (113 loc) · 3.46 KB
/
DList.java
File metadata and controls
131 lines (113 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package fj.data;
import fj.F;
import fj.P;
import fj.control.Trampoline;
import java.util.Iterator;
import static fj.data.List.iterableList;
/**
* Difference List. It converts left associative appends into right associative ones to improve performance.
*
* @version %build.number%
*/
public final class DList<A> {
private final F<List<A>,Trampoline<List<A>>> appendFn;
private DList(final F<List<A>,Trampoline<List<A>>> appendFn) {
this.appendFn = appendFn;
}
/**
* Creates a DList from the function
*
* For alternatives functions to create a DList:
* @see #iterableDList
* @see #iteratorDList
* @see #arrayDList
*/
public static <A> DList<A> dlist(final F<List<A>,Trampoline<List<A>>> f) {
return new DList<>(f);
}
/**
* Creates a DList from a List
*/
public static <A> DList<A> listDList(final List<A> a) {
return dlist((List<A> tail) -> Trampoline.pure(a.append(tail)));
}
/**
* Creates a DList from an Iterable
*/
public static <A> DList<A> iterableDList(final Iterable<A> it) {
return listDList(iterableList(it));
}
/**
* Creates a DList from an Iterator
*/
public static <A> DList<A> iteratorDList(final Iterator<A> it) {
return iterableDList(() -> it);
}
/**
* Creates a DList from an array
*/
@SafeVarargs
public static <A> DList<A> arrayDList(final A...as) {
return listDList(List.list(as));
}
/**
* Concatenates all the internal Lists together that are held in
* the DList's lambda's state to produce a List.
* This is what converts the appending operation from left associative to right associative,
* giving DList it's speed.
* @return the final List
*/
public List<A> run() {
return appendFn.f(List.nil()).run();
}
/**
* Converts the DList to a standard java.util.List.
*/
public java.util.List<A> toJavaList() {
return run().toJavaList();
}
/**
* A empty DList.
* @param <A>
* @return a empty DList.
*/
public static <A> DList<A> nil() {
return new DList<>(Trampoline.pure());
}
/**
* Produces a DList with one element.
* @param <A>
* @param a the element in the DList.
* @return a DList with one element.
*/
public static <A> DList<A> single(A a) {
return new DList<>((List<A> tail) -> Trampoline.pure(tail.cons(a)));
}
/**
* Prepends a single element on the DList to produce a new DList.
* @param a the element to append.
* @return the new DList.
*/
public DList<A> cons(A a) {
return single(a).append(this);
}
/**
* Appends a single element on the end of the DList to produce a new DList.
* @param a the element to append.
* @return the new DList.
*/
public DList<A> snoc(A a) {
return this.append(single(a));
}
/**
* Appends two DLists together to produce a new DList.
* @param other the other DList to append on the end of this one.
* @return the new DList.
*/
public DList<A> append(DList<A> other) {
return new DList<>(kleisliTrampCompose(this.appendFn, other.appendFn));
}
private static <A,B,C> F<A,Trampoline<C>> kleisliTrampCompose(F<B,Trampoline<C>> bc, F<A,Trampoline<B>> ab) {
return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b))));
}
}