Quick examples/samples

294 views
Skip to first unread message

Ted Neward

unread,
Oct 23, 2010, 3:49:29 AM10/23/10
to functio...@googlegroups.com

Does anybody have a quick snippet of how to use the db package from FJ? And ditto for the parallel stuff? I can’t quite figure out the entry point and how to get started, and I’d like to use these two for articles #3 and #4 (with the FJ collections being #2).

 

Ted Neward

Java, .NET, XML Services

Consulting, Teaching, Speaking, Writing

http://www.tedneward.com

 

 

Runar Bjarnason

unread,
Oct 23, 2010, 2:26:40 PM10/23/10
to functio...@googlegroups.com
The db package models database actions as functions from a database connection to some value. F<Connection, A>. For further googling around, this is called the Reader monad. You use it like this:

// DbState encapsulates information about how to get connections.
DbState s = DbState.reader(DBState.driverManager("jdbc:sqlite:/:memory:"));

// A simple DB combinator:
DB<PreparedStatement> prepareStatement(String sql)
  { return new Function<Connection, PreparedStatement>()
    { public PreparedStatement f(c: Connection)
      { return c.prepareSatement(sql); }};
}

Then write a function runStatement of type F<PreparedStatement, DB<ResultSet>>, for example. And then readResults that turns resultsets into hash maps, say. Then you can use monadic bind to compose them like this:

DB<HashMap<String, String>> hm = prepareStatement("select foo, bar from baz").bind(runStatement).bind(readResults);

Threre's not a lot in the db package, but one could add a bunch of useful combinators like that. For example:

DB<B> bracket(DB<A> open, F<A, DB<B>> main, F<A, DB<C>> close)

which you would use to open resultsets or statements, do something with them, and finally close them, all in one action.



The parallel package is simple to use. You first have to pick a parallel Strategy. This is just a way of running something concurrently. Some are provided, for example Strategy.simpleThreadStrategy and Strategy.executorStrategy. There are also some combinators for adorning your strategies with completion detection or error handling. Strategy.strategy takes a function that can be anything you want, so you can make your own strategies.

Then create a parModule:

ParModule pm = ParModule.parModule(myStrategy);

Parmodule has methods for mapping over lists in parallel, zipping, etc. The most important methods on it are the "promise" methods. You can take a P1 and evaluate it in parallel, or promote any F to run in parallel.

Promise basically represents a process. It has some useful methods on it like "fmap" for extending a process with further computation, and "join" for making a process join with a child process. Combine the two and you get "bind" which is monadic bind. This follows the same pattern as DB above. You can write functions of the form F<A, Promise<B>> and compose them with the "bind" method.



--
You received this message because you are subscribed to the Google Groups "Functional Java" group.
To post to this group, send email to functio...@googlegroups.com.
To unsubscribe from this group, send email to functionaljav...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/functionaljava?hl=en.

ant

unread,
Nov 11, 2010, 9:56:42 AM11/11/10
to Functional Java
Runar,

That's is a great idea! Very cool. But there is one thing, I don't
understand: Why DB does not extend F<Connection, A> with (abstract A
f(Connection c)) instead of (abstract A run(Connection c))? In this
case it would get function's stuff for free and could freely cooperate
with other functions (e.g. being an input parameter for
someFunc.bind(...) method).

Many thanks,
Evgeny

On Oct 23, 9:26 pm, Runar Bjarnason <runaror...@gmail.com> wrote:
> The db package models database actions as functions from a database
> connection to some value. F<Connection, A>. For further googling around,
> this is called the Reader monad. You use it like this:
>
> // DbState encapsulates information about how to get connections.
> DbState s = DbState.reader(DBState.driverManager("jdbc:*sqlite*
> > functionaljav...@googlegroups.com<functionaljava%2Bunsu...@googlegroups.com>
> > .

Runar Bjarnason

unread,
Nov 11, 2010, 10:05:11 AM11/11/10
to functio...@googlegroups.com
Because it isn't really a function. It has a side-effect.

> To unsubscribe from this group, send email to functionaljav...@googlegroups.com.

Ted Neward

unread,
Dec 15, 2010, 6:39:59 AM12/15/10
to functio...@googlegroups.com

Sorry for the late reply to this, but I’m finally getting around to trying this (fj.control.db), and I admit that it’s not clicking for me.

 

Couple of questions:

(*) Can’t I create prepareStatement() as an instance of F<Connection, F<String, DB<PreparedStatement>>? Then invoke it as prepareStatement.f(“select foo, bar from baz”)?

(*) Normally/frequently you want to bind parameters into a PreparedStatement; is there a generic way to capture that? Or do I have to write a prepareStatement(String, P2) and prepareStatement(String, P3), … ?

(*) Why does readResults return a HashMap<String,String>? Shouldn’t it return a List<HashMap<String,String>>, since this is a collection of tuples? (Is there any way to use Pn (product) types here?)

(*) DbState.reader() is for when you want to just query the database, correct? Modifications would need to go through a DbState.writer(), correct?

 

I get how the binding would work, so conceptually I’m on board with this; I’m just not seeing how the concepts should map to the concrete, so to speak.

 

Would you happen to have a simple example laying around showing all of this?

Shlomi Vaknin

unread,
Dec 15, 2010, 8:10:21 AM12/15/10
to functio...@googlegroups.com
Hey,
firstly, thanks runar for this explanation, i have been using this approach quite a bit recently, and it sure made things much more fun to do.

Ted, 
I really liked your first article, and i am waiting to read your next :) 

Here is the way i implemented what runar was suggesting, hope that i answer some of your questions... 

this takes in an sql, and returns a wrapping DB operation which prepares the sql

DB<PreparedStatement> prepareStatement(final String sql) {
  return new DB<PreparedStatement>() {
     public PreparedStatement run(Connection c) throws SQLException {
        return c.prepareStatement(sql);
}}}

for a query that a reader might perform, i might have a function like this:

F<PreparedStatement, DB<ResultSet>> runStatement() {
   public DB<ResultSet> f(final PreparedStatement s) {
      return new DB<ResultSet>() {
        public ResultSet run (Connection c) throws SQLException {
           return s.executeQuery();
}}}

or, say i want to execute an updates, so i'd have this:

F<PreparedStatement, DB<Unit>> runUpdate() {
   public DB<Unit> f(final PreparedStatement s) {
      return new DB<Unit>() {
        public Unit run (Connection c) throws SQLException {
           return s.executeUpdate();
}}}

so, to answer your questions, if you want to have extra parameters, you can absolutely have them, without using P's at all, rather by passing them as an argument (like in prepareStatement(final String sql), and you can add as many as you'd like )

also, the only difference between a reader and a writer is the last operation they will perform, either a commit (writer), or rollback (in reader).

to put it all together, you might have something like that:

ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select * from table").bind(runStatement());

this will do all the DB stuff once you execute it, and returns a ready-to-use ResultSet.

this way, you can construct your F's to perform whatever end result you'd like (say something from a ResultSet to a DB<List<Items>> or something), so you can have an entire transaction in a single line, or alternatively, you could compose a transaction in relevant places, but run it only once you are ready to (say in a certain place in the app).

hope this helps..

Shlomi

Runar Bjarnason

unread,
Dec 15, 2010, 10:13:45 AM12/15/10
to functio...@googlegroups.com
> ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select *
> from table").bind(runStatement());

You really should not get a ResultSet out of DB. Instead, write
hasNext of type F<ResultSet,DB<Boolean>> and next F<ResultSet,
DB<Unit>> to step through the result set within the DB monad. Also
don't forget to close your ResultSets.

Runar

Shlomi Vaknin

unread,
Dec 15, 2010, 10:26:17 AM12/15/10
to functio...@googlegroups.com
Thanks :) 
thats a good pointer,

although in my real code, i only return the end of the computation (which is not a db class), so this was just to keep the example short.


Ted Neward

unread,
Dec 15, 2010, 6:43:53 PM12/15/10
to functio...@googlegroups.com

Thanks, Shlomi—I can’t decide between doing article #2 on collections or on the DB stuff. I think I need to do collections (List, Array, Tree, etc) next, but the DB stuff is kinda sexy, so…. *shrug* Oh, well, guess I have to consider writing more. :-)

 

But I need a bit of clarification on your sample code here. Runar, if you can join in, that’d be great.

 

> so, to answer your questions, if you want to have extra parameters, you can absolutely have them, without using P's at all, rather by passing them as an argument (like in prepareStatement(final String sql), and you can add as many as you'd like )

OK, but that means I have to write an overloaded prepareStatement() method for each arity and/or type of parameter I want to pass in. That seems wasteful—is there no way to compose that? (Part of me wants to reach for varargs or a List<> for the parameters, but I suspect that’s my O-O lizard brain talking. Maybe that’s an OK solution, but I want to exhaust the functional axis before I go back to what I know already.)

 

> ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select * from table").bind(runStatement());

I think you’re missing a right-parens here, and I’m not in front of a Java command prompt to experiment, so I’m just going to ask—is the bind() against the return from DbState.reader(), or against the return from prepareStatement()? (There’s bind() on both, if I remember correctly, hence my confusion.) And if I wanted to do as Runar suggested (convert the ResultSet into a List-of-Map<String,Object> or List<Person> before handing it back), would that be inside the run()? Where does the bind() go in that case, is what I’m asking?

 

Part of me *wants* to see the DB stuff return Pn instances out of a query, because that provides a nicely-typed bundle of data to use in a constructor to an object.

Runar Bjarnason

unread,
Dec 15, 2010, 6:59:38 PM12/15/10
to functio...@googlegroups.com
> Maybe that’s an OK solution, but I want to exhaust the
> functional axis before I go back to what I know already.)

What I've done in the past is to have an ADT for SQL, complete with
"holes" for bind variables (or literals, as the mood may strike you).
Then have an F<SQL, DB<PreparedStatement>>.

> is the bind() against
> the return from DbState.reader(), or against the return from
> prepareStatement()? (There’s bind() on both, if I remember correctly, hence
> my confusion.) And if I wanted to do as Runar suggested (convert the
> ResultSet into a List-of-Map<String,Object> or List<Person> before handing
> it back), would that be inside the run()? Where does the bind() go in that
> case, is what I’m asking?

Follow the types. If you want to convert ResultSet to List<Person>,
you would pass an F<ResultSet, DB<List<Person>>> to .bind() on an
object of type DB<ResultSet>.

Mind you, this is a really good excuse to use iteratees. It's too bad
we don't provide that interface in FJ.

> Part of me *wants* to see the DB stuff return Pn instances out of a query,
> because that provides a nicely-typed bundle of data to use in a constructor
> to an object.

Pro tip: Don't ever have DB.run return anything other than Unit. Don't
get data OUT. Put computations over that data IN with .map() and
.bind().

Runar

Ted Neward

unread,
Dec 15, 2010, 7:51:23 PM12/15/10
to functio...@googlegroups.com
> What I've done in the past is to have an ADT for SQL, complete with
"holes"
> for bind variables (or literals, as the mood may strike you).
> Then have an F<SQL, DB<PreparedStatement>>.
>
Where SQL is a....F? Instance of something else?

> > Part of me *wants* to see the DB stuff return Pn instances out of a
> > query, because that provides a nicely-typed bundle of data to use in a
> > constructor to an object.
>
> Pro tip: Don't ever have DB.run return anything other than Unit. Don't get
> data OUT. Put computations over that data IN with .map() and .bind().
>

OK, now you're intriguing me--is there a quick example you can send? Are you
advocating something like a SELECT FOR UPDATE or something?

Ted Neward
Java, .NET, XML Services
Consulting, Teaching, Speaking, Writing
http://www.tedneward.com

> -----Original Message-----
> From: functio...@googlegroups.com
> [mailto:functio...@googlegroups.com] On Behalf Of Runar Bjarnason
> Sent: Wednesday, December 15, 2010 4:00 PM
> To: functio...@googlegroups.com
> Subject: Re: [functionaljava] Quick examples/samples
>

Tony Morris

unread,
Dec 15, 2010, 8:18:55 PM12/15/10
to functio...@googlegroups.com
On 16/12/10 09:59, Runar Bjarnason wrote:
> Mind you, this is a really good excuse to use iteratees. It's too bad
> we don't provide that interface in FJ.
>
>
Erik Meijer, who works for MS SQL team, gave a talk on this recently at
YOW! conference. I hope the video will be up some time soon. Of course,
it wasn't called "iteratees" in keeping with the "let's steal good ideas
and name them something else" theme from Microsoft.

--
Tony Morris
http://tmorris.net/


Runar Bjarnason

unread,
Dec 15, 2010, 8:26:48 PM12/15/10
to functio...@googlegroups.com
> Where SQL is a....F? Instance of something else?

Something like...

public interface SQL {
public <B> B eval(F<Select, B> select, F<F<SQLVar, SQL>, B> freeVar,
F<SQLVar, B> boundVar);
}

public interface Select {
public <B> B eval(F<Map<String, Expr>> select, F<Map<String, SQL>,B>
from, F<Map<String, Expr>> where);
}

public interface Expr {
public <B> B eval(F3<String, B, B, B> binary, F2<String, B, B, B>
unary, F2<SQLLit, B> literal, F2<SQLVar, B> variable);
}

public interface SQLLit {
public <B> B eval(F<String, B> string, F<Integer, B> integer, ... );
}

public interface SQLVar {
public <B> B eval(F<String, B> string, F<Integer, B> integer, ...);
}

Alternatively, a simple intermingling of variables and string literals:

public interface SQL {
public <B> B eval(F2<B, B, B> append, F<String, B> literal,
F<SQLVar, B> variable);
}

> OK, now you're intriguing me--is there a quick example you can send? Are you
> advocating something like a SELECT FOR UPDATE or something?

No, I'm advocating doing all of your computation with functions of
type F<A, DB<B>>, for some A and B, wherever you have to use data of
type A that comes from the database (producing B). For example, if you
have DB<String> x and you want to println that String, don't run that
x. Instead, call x.map() with an argument of type F<String, DB<Unit>>
which prints the string. This is how you stay composable.


Runar

Ted Neward

unread,
Dec 15, 2010, 8:59:05 PM12/15/10
to functio...@googlegroups.com
I'm sorry, Runar, I'm just not seeing it. How would I use these? I can see
the vague outlines of where you're going with this, but putting it together
is what's confounding me.

Fred Janon

unread,
Dec 16, 2010, 2:52:53 AM12/16/10
to functio...@googlegroups.com
Hi Ted,

Are your articles on the Web? I could not find them.

Thanks

Fred

Ted Neward

unread,
Dec 16, 2010, 2:57:06 AM12/16/10
to functio...@googlegroups.com

The first one will run in the NFJS Journal (which I think went out this month). A second will run in the Feb or March issue of the same periodical.

 

After a reasonable period of time, I’ll post them to my website, but the usual arrangement is that the articles run exclusively in the publication for a while first.

 

Of course, if you’re in this group, you could check the archives back about a month or so—I posted the text for the first article here for (extremely helpful!) review.

Fred Janon

unread,
Dec 16, 2010, 3:23:05 AM12/16/10
to functio...@googlegroups.com
Great, thanks Ted.

Fred

i84c0re

unread,
Dec 16, 2010, 4:45:22 AM12/16/10
to Functional Java


On 16 Dez., 00:59, Runar Bjarnason <runaror...@gmail.com> wrote:
> ... iteratees. It's too bad
> we don't provide that interface in FJ.
> ...

Are there any plans on changing this fact?

Runar Bjarnason

unread,
Dec 16, 2010, 10:38:23 AM12/16/10
to functio...@googlegroups.com
>> ... iteratees. It's too bad
>> we don't provide that interface in FJ.
>> ...
>
> Are there any plans on changing this fact?

No immediate plans, but it would not be difficult to write pure
iteratees in Java.

Shlomi Vaknin

unread,
Dec 18, 2010, 5:00:17 AM12/18/10
to functio...@googlegroups.com
>I'm sorry, Runar, I'm just not seeing it. How would I use these?
yes, runar got me on this one too.

>I think you’re missing a right-parens here, and I’m not in front of a Java command prompt to experiment
no - i was binding the prepareStatement, not the reader. The idea wsa to compose another operation over the prepareStatement DB operation. And I have to agree with Runar, we should only return a DB<Unit> at the end, nothing else. if there is something else we might want to return, we might as well turn it into an F<A, DB<Unit>> and compose it also before we hit reader.run

Regarding your article #2, i really believe you should make one on the dataypes and collections, since people who are either new to FJ or wants to see if its any good for them will want to know how this library helps them with everyday things (like making a collection and mapping an effect over it, or doing lazy evals with Streams), rather then DB stuff, which is a bit more advanced, and less casual. Perhaps DB will make a great topic for article #3 ;)

Shlomi

Ted Neward

unread,
Dec 19, 2010, 5:44:19 PM12/19/10
to functio...@googlegroups.com

Yep, that was kinda where my mind ended up. #2 will probably not be due for a few months yet, but I’m going to try and slam two or three of them out over the holidays and try to get ahead of my deadlines for a change. :-)

Reply all
Reply to author
Forward
0 new messages