forked from functionaljava/functionaljava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDB.java
More file actions
120 lines (109 loc) · 3.5 KB
/
DB.java
File metadata and controls
120 lines (109 loc) · 3.5 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
package fj.control.db;
import fj.F;
import fj.Function;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.Callable;
/**
* The DB monad represents a database action, or a value within the context of a database connection.
*/
public abstract class DB<A> {
/**
* Executes the database action, given a database connection.
*
* @param c The connection against which to execute the action.
* @return The result of the action.
* @throws SQLException if a database error occurred.
*/
public abstract A run(final Connection c) throws SQLException;
/**
* Constructs a database action as a function from a database connection to a value.
*
* @param f A function from a database connection to a value.
* @return A database action representing the given function.
*/
public static <A> DB<A> db(final F<Connection, A> f) {
return new DB<A>() {
public A run(final Connection c) {
return f.f(c);
}
};
}
/**
* Returns the callable-valued function projection of this database action.
*
* @return The callable-valued function which is isomorphic to this database action.
*/
public final F<Connection, Callable<A>> asFunction() {
return new F<Connection, Callable<A>>() {
public Callable<A> f(final Connection c) {
return new Callable<A>() {
public A call() throws Exception {
return run(c);
}
};
}
};
}
/**
* Map a function over the result of this action.
*
* @param f The function to map over the result.
* @return A new database action that applies the given function to the result of this action.
*/
public final <B> DB<B> map(final F<A, B> f) {
return new DB<B>() {
public B run(final Connection c) throws SQLException {
return f.f(DB.this.run(c));
}
};
}
/**
* Promotes any given function so that it transforms between values in the database.
*
* @param f The function to promote.
* @return A function equivalent to the given one, which operates on values in the database.
*/
public static <A, B> F<DB<A>, DB<B>> liftM(final F<A, B> f) {
return new F<DB<A>, DB<B>>() {
public DB<B> f(final DB<A> a) {
return a.map(f);
}
};
}
/**
* Constructs a database action that returns the given value completely intact.
*
* @param a A value to be wrapped in a database action.
* @return A new database action that returns the given value.
*/
public static <A> DB<A> unit(final A a) {
return new DB<A>() {
public A run(final Connection c) {
return a;
}
};
}
/**
* Binds the given action across the result of this database action.
*
* @param f The function to bind across the result of this database action.
* @return A new database action equivalent to applying the given function to the result of this action.
*/
public final <B> DB<B> bind(final F<A, DB<B>> f) {
return new DB<B>() {
public B run(final Connection c) throws SQLException {
return f.f(DB.this.run(c)).run(c);
}
};
}
/**
* Removes one layer of monadic structure.
*
* @param a A database action that results in another.
* @return A new database action equivalent to the result of the given action.
*/
public static <A> DB<A> join(final DB<DB<A>> a) {
return a.bind(Function.<DB<A>>identity());
}
}