Hello,After much scratching of my head over intricate parts of this "Haskell" thingI'm happy to announce that I've finally released my first effort in it: HaskRel.Overview--------Because I've spent quite a bit of time on database prompts I thought it would bea fun exercise to see how much GHC can be made to operate like a DBMS, and howmuch of the relational model of database management (as defined by Chris Date etal. today) I'm able to make it accommodate. I'm pleased to register that therelational algebra, base variables and assignment works as one would expect at adatabase prompt. It does not qualify as an actual RDBMS (unsurprisingly),since it doesn't implement many other things that are required for it to be aproper RDBMS, either because I haven't gotten around to it or they cannot beimplemented in Haskell.I've put the source up on GitHub and published it on Hackage:Hackage:GitHub:HaskRel employs a Data.Set of Data.HList.Record as a relation type, for which itdefines "Relation" as a synonym. It supports base variables (files) of thistype, and implements the functions of the relational algebra such that they canbe expressed upon both constants or literal values, upon variables, and uponexpressions on variables.Example-------The following is a minimal definition of a database with a single relationvariable, "sp":module MiniDB whereimport Data.HList.CommonMainimport Database.HaskRel.RDBMSsp :: Relvar '[Attr "sno" String,Attr "pno" String,Attr "qty" Integer]sp = Relvar "SP.rv""Attr" has been defined as a synonym for "Data.Tagged.Tagged", because that isemployed to represent what are known as attributes in relational theory. Loadingthis in GHCi we can first create a relation constant, do some relationalassignment, and print the results (pardon the long lines):*MiniDB> let s = ( relation' [ ( "S1", "Smith", 20, "London" ), ( "S2", "Jones", 10, "Paris" ), ( "S3", "Blake", 30, "Paris" ) ] :: Relation '[Attr "sno" String, Attr "sName" String, Attr "status" Integer, Attr "city" String] )*MiniDB> pt s┌───────────────┬─────────────────┬───────────────────┬────────────────┐│ sno :: String │ sName :: String │ status :: Integer │ city :: String │╞═══════════════╪═════════════════╪═══════════════════╪════════════════╡│ S1 │ Smith │ 20 │ London ││ S2 │ Jones │ 10 │ Paris ││ S3 │ Blake │ 30 │ Paris │└───────────────┴─────────────────┴───────────────────┴────────────────┘*MiniDB> sp `assign` ( relation' [ ("S1", "P1", 300), ("S1", "P3", 400), ("S1", "P5", 100), ("S2", "P1", 300), ("S3", "P2", 200) ] :: Relation '[Attr "sno" String, Attr "pno" String, Attr "qty" Integer] )Value assigned to ./SP.rv*MiniDB> pt sp┌───────────────┬───────────────┬────────────────┐│ sno :: String │ pno :: String │ qty :: Integer │╞═══════════════╪═══════════════╪════════════════╡│ S1 │ P1 │ 300 ││ S1 │ P3 │ 400 ││ S1 │ P5 │ 100 ││ S2 │ P1 │ 300 ││ S3 │ P2 │ 200 │└───────────────┴───────────────┴────────────────┘(Mind that correct display of the Unicode table drawing characters depends onusing the right fixed-width font.)Fundamental operations of the relational algebra can of course be performed onthem:*MiniDB> p $ s `naturalJoin` sp┌─────┬───────┬────────┬────────┬─────┬─────┐│ sno │ sName │ status │ city │ pno │ qty │╞═════╪═══════╪════════╪════════╪═════╪═════╡│ S1 │ Smith │ 20 │ London │ P1 │ 300 ││ S1 │ Smith │ 20 │ London │ P3 │ 400 ││ S1 │ Smith │ 20 │ London │ P5 │ 100 ││ S2 │ Jones │ 10 │ Paris │ P1 │ 300 ││ S3 │ Blake │ 30 │ Paris │ P2 │ 200 │└─────┴───────┴────────┴────────┴─────┴─────┘A proper relational database management system (which, again, this isn't, forseveral other reasons) must support type inference for relational expressions(see The Third Manifesto, relational model prescription 18). Fortunately, thatis of course no problem for GHC with the right extensions:*MiniDB> :t ss :: Relation'[Attr "sno" String, Attr "sName" String, Attr "status" Integer,Attr "city" String]*MiniDB> :t spsp:: Relvar'[Attr "sno" String, Attr "pno" String, Attr "qty" Integer]*MiniDB> :t s `naturalJoin` sps `naturalJoin` sp:: IO(containers-0.5.6.2:Data.Set.Base.Set(RTuple'[Tagged "sno" String, Tagged "sName" String,Tagged "status" Integer, Tagged "city" String, Tagged "pno" [Char],Tagged "qty" Integer]))DML is also supported, of course:*MiniDB> insert sp ( relation' [ ("S1", "P2", 200), ("S1", "P3", 400), ("S1", "P4", 200) ] :: Relation '[Attr "sno" String, Attr "pno" String, Attr "qty" Integer] )Inserted 2 of 3 tuples into ./SP.rvConcise expression of "update" require a set of language extensions (this inaddition to DataKinds, which this module enables by default since it is quiteubiquitous in this endeavor):*MiniDB> :set -XQuasiQuotes -XKindSignatures -XViewPatterns*MiniDB> :{*MiniDB| update sp (\[pun|pno qty|] -> ( pno == "P2" || pno == "P3" || pno == "P4" ) && qty < 300 )*MiniDB| (\[pun|qty|] -> case qty + 50 of qty -> [pun|qty|])*MiniDB| :}Updated 3 of 7 tuples in ./SP.rv*MiniDB> pt$ sp `restrict` \[pun|pno|] -> ( pno == "P2" || pno == "P3" || pno == "P4" )┌───────────────┬───────────────┬────────────────┐│ sno :: String │ pno :: String │ qty :: Integer │╞═══════════════╪═══════════════╪════════════════╡│ S1 │ P2 │ 250 ││ S1 │ P3 │ 400 ││ S1 │ P4 │ 250 ││ S3 │ P2 │ 250 │└───────────────┴───────────────┴────────────────┘And of course delete-by-predicate:*MiniDB> count sp7*MiniDB> deleteP sp (\[pun|pno|] -> pno == "P3")Deleted 1 tuples from SP.rv*MiniDB> count sp6For an overview of the functions of the relational algebra and relationalassignment defined by HaskRel see:Summary-------This is a personal, spare-time project, the motivations for which have been tolearn Haskell, and see how much of the relational model Haskell/GHC canaccommodate, or how much like an RDBMS GHC can operate. Making this practicallyusable has not been part of the scope.Ascertaining that Haskell/GHC accommodates the relational algebra, relationalbase variables and operations thereupon in such a straight forward manner, wasquite nice. It was particularly fun to see how this allowed examples ofexpressions in Tutorial D from Chris Date's "SQL and Relational Theory, 2nd. ed"to be expressed in Haskell in a manner quite verbatim to the originals (seeand chapters 6 and 7 of said book). It was also interesting to see trivialquerying and DML operations on GHCi operate in a manner similar to what onewould expect in a DBMS.Even if this isn't of practical use I still hope it is of some interest, or atleast that it can enable Haskell as a demonstrator of some parts of therelational model for database management.Thanks,Thor Michael Støre
_______________________________________________
Haskell mailing list
Haskell@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell