HaskRel-0.1.0.1: examples/SuppliersPartsDB/Default.hs
{-# LANGUAGE DataKinds #-}
{-|
Default contents for the SuppliersPartsDB.
-}
module SuppliersPartsDB.Default where
import Database.HaskRel.Relational.Definition ( Relation, relation, relation', rTuple )
import SuppliersPartsDB.Definition
import Data.HList.CommonMain ((.=.))
{-
Tutorial D:
RELATION
{ TUPLE { SNO ‘S1’ , SNAME ‘Smith’ , STATUS 20 , CITY ‘London’ } ,
TUPLE { SNO ‘S2’ , SNAME ‘Jones’ , STATUS 10 , CITY ‘Paris’ } ,
TUPLE { SNO ‘S3’ , SNAME ‘Blake’ , STATUS 30 , CITY ‘Paris’ } ,
TUPLE { SNO ‘S4’ , SNAME ‘Clark’ , STATUS 20 , CITY ‘London’ } ,
TUPLE { SNO ‘S5’ , SNAME ‘Adams’ , STATUS 30 , CITY ‘Athens’ } }
In Tutorial D attribute identifiers can both be used without arguments (within a
query to denote a attribute of a relation in scope), or with an argument as
above, as a attribute constructor. The same can be achieved in Haskell in
various ways. One way is defining all pertinent functions such that they allow
both a label and a constructor without an argument, and then only defining such
constructors:
status a = (Label::Label "status") .=. (a::Integer)
Which would allow:
rTuple ( sno "S1" , sName "Smith" , status 20 , city "London" )
While still letting one use sno, sName, etc as attribute identifiers in
functions. However, doing this consistently requires some rather convoluted
type-level acrobatics that causes exponential growth in function definition
complexity. As such only labels are defined in these examples, which one must
use .=. to construct into the tagged values that are directly employed by
HaskRel as relational attributes.
An alternative would be
https://hackage.haskell.org/package/HList/docs/Data-HList-Labelable.html, though
HaskRel records don't build on lens and can't accomodate that approach as-is.
-}
s' =
relation
[ rTuple ( sno .=. "S1" , sName .=. "Smith" , status .=. 20 , city .=. "London" ) ,
rTuple ( sno .=. "S2" , sName .=. "Jones" , status .=. 10 , city .=. "Paris" ) ,
rTuple ( sno .=. "S3" , sName .=. "Blake" , status .=. 30 , city .=. "Paris" ) ,
rTuple ( sno .=. "S4" , sName .=. "Clark" , status .=. 20 , city .=. "London" ) ,
rTuple ( sno .=. "S5" , sName .=. "Adams" , status .=. 30 , city .=. "Athens" ) ]
:: Relation '[SNO, SName, Status, City]
p' =
relation
[ rTuple ( pno .=. "P1" , pName .=. "Nut" , color .=. "Red" , weight .=. 12.0 , city .=. "London" ) ,
rTuple ( pno .=. "P2" , pName .=. "Bolt" , color .=. "Green" , weight .=. 17.0 , city .=. "Paris" ) ,
rTuple ( pno .=. "P3" , pName .=. "Screw" , color .=. "Blue" , weight .=. 17.0 , city .=. "Oslo" ) ,
rTuple ( pno .=. "P4" , pName .=. "Screw" , color .=. "Red" , weight .=. 14.0 , city .=. "London" ) ,
rTuple ( pno .=. "P5" , pName .=. "Cam" , color .=. "Blue" , weight .=. 12.0 , city .=. "Paris" ) ,
rTuple ( pno .=. "P6" , pName .=. "Cog" , color .=. "Red" , weight .=. 19.0 , city .=. "London" ) ]
:: Relation '[PNO, PName, Color, Weight, City]
-- Let's say that I'm tired of repeating the attribute names; syntactic sugar to
-- the rescue, note the use of relation' instead of relation, and that the type
-- annotation becomes mandatory:
sp' =
relation'
[ ("S1", "P1", 300),
("S1", "P2", 200),
("S1", "P3", 400),
("S1", "P4", 200),
("S1", "P5", 100),
("S1", "P6", 100),
("S2", "P1", 300),
("S2", "P2", 400),
("S3", "P2", 200),
("S4", "P2", 200),
("S4", "P4", 300),
("S4", "P5", 400) ] :: Relation '[SNO, PNO, QTY]
{-
Also note how the attribute names above, SNO etc, are declared type synonyms in
Definition.hs, and not ad-hoc. An equivalent ad-hoc definition would be:
Relation '[Tagged "sno" String, Tagged "pno" String, Tagged "qty" Integer]
An alternative approach is to define constructors for each label, which would
also make it more type-safe:
sno' a = (Label :: Label "sno") .=. a :: SNO
There may be a way to build the functions of the relational algebra such that
they accept both "Label l" and "v -> Tagged l v" types, which would make it
possible that instead of label constants one could just define constructors and
used those against the functions of the relational algebra, but an investigation
into that revealed no attempt that didn't have an unacceptable drawback.
-}