Introducing furious – a proof-of-concept RRM for F#
13 Jul 2010 09:29 PM UncategorizedOne of the first things that newcomers to F# look for is an ORM system, be it a native one, or an adaptation of something already present. Since there are plenty of systems in the .net ecosystem, it is possible to get one of them to work with F#. But as we start to do that, the more seasoned f#'er will notice that something is amiss. One of the core tenets of F# is immutability, and classic ORMs rely on mutability by operating on class properties. While F# does support classes with mutable properties, the preferred unit of work is the record. This also follows the representation of the database better - at any one point in time you're either holding an uncommited record, or a representation of database state; immutability there prevents any confusion. These considerations, and discussions with some of the F# folks out there (Aaron Erickson being a major influencer of this idea), I decided to put something together meant for F# specifically.
Meet furious. Furious is a RRM - a Record Relation Mapping system. It is a database-independent object query dsl for records, that currently has a (barebones) mysql implementation. Here's how it works. Suppose you have a record graph like so:
personId: string
firstname: string
lastname: string
homeAddress: address
workAddress: address
altAddresses: address seq
}
and address = {
addressId: string
street1: string
zip: string
}
Now, if i wanted the list of all people that live in the 60614 zipcode, i could write this:
db.Yield <@ Seq.filter (fun p -> p.homeAddress.zip = "60614") @>
That's it. Neat, huh? Now, if you wanted something like a count of all such neighbors, you could do this:
db.Compute <@ fun people -> Seq.length <| Seq.filter (fun p -> p.homeAddress.zip = "60614") people @>
The main idea behind furious is to avoid inventing a new dsl, and use what's already there - the concepts defined over the Sequence space. Furious provides two methods - Yield (expr: Expr<(seq<'a>->seq<'b>)>), and Compute (expr: Expr<(seq<'a>->'b)>). The idea is that one is for mapping one sequence into another, and the other is for computing a value from a sequence (such as our Seq.length example). The interesting thing is that this approach is enough to cover a majority of all orm/rrm usecases. While there are statements that can't (easily) be expressed this way, they reach a complexity level that should really be done via explicit sql, rather than this type of generation.
Furious is currently a proof-of-concept project that will evolve into a full library. It currently lacks a lot of major features, and has only been tested for a handful of scenarios. That said, I welcome input and contribution, as this is a complex project that needs more than one mind.
The code is located here: http://github.com/kolosy/furious
Looks interesting!
There is a small typo in your first example, instead of:
p.homeAddress.zip = z
you probably intended:
p.homeAddress.zip = “60614″
BTW: There’s a very nice interview of Don Syme done by Tim Anderson where Don Syme says this:
“What’s ahead – there’s another set of things which are very close to my heart. One of the key things that makes F# work as a language is that once you have the data under the strongly typed discipline of functional programming, then working with the data is extremely fluent and sweet. One of the things we’d like to work on is the transition point between the world of data coming in from the outside and the world of strongly typed programming within F#. You’ll see in future versions of F# huge advances in how we acquire data from external sources, whether those be databases or whether those be internet-hosted databases, or whether they be XML files. Making it even easier to get your hands on the data that drives your work.”
http://www.itwriting.com/blog/articles/don-syme-on-f-microsofts-functional-programming-language-for-net
Jarle
oops, good point. fixed.
re: don syme’s commment – i hope so. if there’s something native that makes this stuff obsolete (or forces me to develop something better/faster/smarter) then so much the better. i think the things we’ve seen come out of the f# team have been excellent, and quite different from other microsoft mass-production.