Contextureにおけるgroupby

(下書きです。)
Contextureはfunctional database modelをベースとしたDBMSです。
Dataflowもしくはfunctional reactive programmingな仕組みを取り入れています。
functional database modelは、永続化された辞書や連想配列などのデータ構造を
関数と見なして操作するデータベースモデルです。
関数なので、KVSと同じように、キーをつっこめば値が得られる、というのが一番基本的なクエリーになります。
関数なので、複数の関数の合成、つまり直列につなぐ事や並列につなぐことができます。

関数の合成や操作は、HaskellのArrowと雰囲気は同じです。
http://d.hatena.ne.jp/r-west/20070720/1184946510

Arrowでは直列につなぐ演算子は「>>>」ですが、
Contextureではただの「.」(ドット)を使います。
Contextureでは多値を返す関数を基本として、合成操作もすこし拡張してありますが、
その説明はまた今度。

社員や、部署の関係をあらわすデータを例にとります。
所属 :: 社員ID -> 部署ID
所属 = {1:[101],2:[101], 3:[102], 4:[101]}

社員名 :: 社員ID -> String
社員名 = {1:["田中"], 2:["鈴木"], 3:["山田"], 4:["後藤"]}


部署名 :: 部署ID -> String
部署名 = {101:["開発部"], 102:["人事部"]}

年齢 :: 社員ID -> Integer
年齢 = {1:[30], 2:[30],3:[30], 4:[40]}

[1] => 所属.部署名 => ["開発部"]
[1, 3] => 所属.部署名 => ["開発部", "人事部"]

[1] => (所属.部署名,社員名) => [("開発部", "田中")]

~は、inverseの単項演算子です。
~所属は、所属のinverseで、
所属 :: 社員ID -> 部署ID
所属 = {1:[101],2:[101], 3:[102], 4:[101]}
なので、
~所属 :: 社員ID -> 部署ID
~所属 = {101:[1,2,4],102:[3],}
になります。

[101] => (部署名, ~所属.(社員名,年齢))
=> [
   ("開発部", [
     ("田中", 30), ("鈴木", 30), ("後藤", 40)]),
   ("開発部", [
     ("山田", 30)])]


今回はContextureにおけるgroupbyについていまのところ考えている仕様を説明します。
groupbyは、ある属性でまとめるような操作になります。
groupby(~所属, 年齢)
は、~所属を 年齢でグルーピングする感じです。

型は
groupby(~所属, 年齢) :: 部署ID -> Integer -> 社員ID
になります。つまり、部署IDが決まって、Integer(年齢)がきまって
初めて社員IDが得られる、引数を二つとる関数のようなものになります。
データ構造としては、辞書の入れ子になります。
カリー化された関数のようなかんじです。

データは、
groupby(~所属, 年齢) = {
 101:{
  30:[1, 2],
  40:[4]},
  102:{
   30:[3]}}

のようになります。
例としては、つぎのようなかんじになります。

[101] => groupby(~所属, 年齢)
=> [{
  30:[1, 2],
  40:[4]}]
[101] => groupby(~所属, 年齢).社員名
=> [{
  30:["田中", "鈴木"],
  40:["後藤"]}]