-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | HaskRel, Haskell as a DBMS with support for the relational -- algebra -- -- HaskRel aims to define those elements of the relational theory of -- database management that Haskell can accommodate, thus enabling -- Haskell (or more precisely GHC) in its own right as a DBMS with -- first-class support for those parts of the relational model. It does -- not qualify as a proper RDBMS since it as-is only defines the -- relational algebra, relational variables and relational assignment. It -- does not define the relational calculus, views, constraints and -- transactions (beyond the fundamental requirement that the tuples of -- relations are to be unique), certain operators like relation valued -- aggregate operators, nor a few minor or even deprecated operators such -- as DIVIDE. The implemented parts are decently complete even if there -- are major implementation shortcomings that prevent this from being -- practically usable as an actual DBMS. -- -- I refer to it as "first-class" since the types of the -- relational model are first-class types to Haskell, and the Haskell -- type system is able to induce the type resulting of relational -- expressions (for instance that a natural join of two relations results -- in a relation with a heading that is the setwise union of the headings -- of the original relations). -- --

Examples

-- -- The examples in this documentation are based on "the old warhorse" -- that is the suppliers-parts database (see [1] for more). This gives a -- body of relational expressions with known results to base examples -- upon. See also examples/SuppliersPartsExamples.hs (not visible from -- this documentation) for Haskell versions of a selection of the -- Tutorial D expressions given as examples in chapters 6 and 7 of [1]. -- These can be run by starting examples/suppliersPartsDB.sh and then -- running snrt2ndExamples. While most Tutorial D expressions -- translate fairly verbatim to Haskell there are a few where one must be -- a bit more explicit. While most Tutorial D expressions translate -- fairly verbatim to Haskell there are a few where Haskell is stricter -- than Tutorial D and one must be a bit more explicit. -- -- $ is always used after p/rPrint or -- pt/rPrintTyped in the examples to keep them uniform (and -- so it kinda looks like a prompt), even when not required. The short -- forms p and pt are used whenever there isn't a conflict -- with other identifiers, whereas for the SuppliersPartsExample, which -- has a relvar "p", rPrint is used instead of p -- for presentation of relational objects without type information. -- --

Terminology

-- -- Since this builds on both Haskell and relational theory this -- documentation uses terms as they have been established in material -- related to either. Several terms of Haskell and HList have been -- redefined in terms of relational theory in this library, mostly to -- illustrate how terms and concepts have been mapped from the latter to -- the former. (I'm trying to keep this open to change later if it turns -- out to be an unhelpful crutch.) -- -- The following table gives a quick overview of either terms or concepts -- as found in Haskell, the relational model (as presented in [1]), -- HaskRel and SQL, and how they are mapped from the second to the first: -- --
--   ┌───────────────────────────┬────────────────────┬────────────┬────────────────────────────────────────────────┐
--   │ haskell                   │ relModel           │ haskRel    │ sql                                            │
--   ╞═══════════════════════════╪════════════════════╪════════════╪════════════════════════════════════════════════╡
--   │ Data.Tagged.Tagged        │ attribute          │ Attr       │ field, column                                  │
--   │ Data.HList.Record.Record  │ tuple              │ RTuple     │ row                                            │
--   │ ( Set (Record a) )        │ relation           │ Relation a │ table                                          │
--   │ FilePath (Set (Record a)) │ relvar             │ Relvar a   │ table                                          │
--   │ Data.HList.Record.Label   │ attribute name     │ Label      │ field name, column name                        │
--   │ Data.HList.Record.Labels  │ attribute name set │ Labels     │ list of field/column names                     │
--   │ function, operator        │ operator           │ function   │ operator, function, procedure, routine, method │
--   └───────────────────────────┴────────────────────┴────────────┴────────────────────────────────────────────────┘
--   
-- -- Found in "example/Terminology.hs". Note that this is just an overview, -- study of [1] or [2], Haskell itself, HList and HaskRel is required to -- see how terms and concepts correlate. -- -- The term "RTuple", or "r-tuple", is chosen to simultaneously -- distinguish the concept from Haskell tuples while relating it to -- tuples of the relational model. For the type of either "Record a" or -- "Set ( Record a )" in Haskell the term "heading" is used in relational -- theory, and "row type" or "composite type" in SQL. In relational -- theory the term "scalar" is used to refer to data types that are -- neither tuples nor relations, which corresponds to everything but -- "Record a" or "Set ( Record a )" in Haskell. Note also that HaskRel -- does use the term "table", but then only in the sense of -- "presentation of a relation value" (see above). -- --

The HaskRel library

-- -- Not all modules of this library are relevant to gain an understanding -- of how it functions, the next part to go to at this point is -- Database.HaskRel.RDBMS, and the modules it reexports. -- -- @package HaskRel @version 0.1.0.1 -- | Presentation of tables in a two-dimensional fixed-width font form. module Database.HaskRel.FWTabulation -- | Builds a one-line representation of a value, plus header present1LineValue :: [[String]] -> [String] -> [String] -- | Builds a multi-line representation of a value, plus header presentNLineValue :: [[[String]]] -> [String] -> [String] -- | Given two lists of orderables, produces a list of equal length where -- each element is that which is the maximum of those elements that are -- in the same position in the two input lists. maxLen :: Ord b => [b] -> [b] -> [b] -- | Transposes a list of lists of lists, padding the lists of the second -- dimension with empty lists if they are shorter than the other rows. padTranspose :: [[[t]]] -> [[[t]]] -- | HList fixed-width tabular presentation. Presentation of HList values -- in a two-dimensional, tabular fixed-width font form with a header -- consisting of labels and optionally types. Only records are supported -- by this module, see TIPFWTabulation for support for TIPs. module Database.HaskRel.HFWTabulation class HFWPresent r where hfwPrintTyped = hfwPrintTypedTS EmptyTS hfwPrint :: HFWPresent r => r -> IO () hfwPrintTyped :: HFWPresent r => r -> IO () hfwPrintTypedTS :: (HFWPresent r, HListTypeSynonym ts) => ts -> r -> IO () class Show a => FWPresent a fwPresent :: FWPresent a => a -> [String] fwPresentTyped :: FWPresent a => a -> [String] class Show a => FWPresent' flag a fwPresent' :: FWPresent' flag a => flag -> a -> [String] fwPresentTyped' :: FWPresent' flag a => flag -> a -> [String] -- | Prints a set of HList records in a table format printHRecSetTab :: (Typeable [*] a, RecordValues a, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]]) => Set (Record a) -> IO () -- | Prints a set of HList records in a table format, with types in the -- header printHRecSetTabTyped :: (Typeable [*] a, RecordValues a, HFoldr (Mapcar HPresentTypedRecAttr) [[String]] (RecordValuesR a) [[String]]) => Set (Record a) -> IO () -- | Prints a set of HList records in a table format, with types that use -- the given type synonyms in the header printHRecSetTabTypedTS :: (Typeable [*] a, RecordValues a, HFoldr (Mapcar HPresentTypedRecAttr) [[String]] (RecordValuesR a) [[String]], HListTypeSynonym ts) => ts -> Set (Record a) -> IO () showHRecSetTab :: (Typeable a, RecordValues a, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]]) => Set (Record a) -> String -- | Show a TypeRep showTR :: TypeRep -> String -- | Show a TypeRep, using the given type synonyms showTRTS :: HListTypeSynonym ts => ts -> TypeRep -> String showHTypeTS :: HListTypeSynonym ts => ts -> TypeRep -> String showHListSetType :: (Typeable r, Typeable a) => Set (r a) -> String data HFWTIPSet data HFWTIP data HFWRec data HFWString data HFWOther -- | Type synoyms used when building the table header with type names class HListTypeSynonym s hRecTS :: HListTypeSynonym s => s -> String hRecSetTS :: HListTypeSynonym s => s -> String hTIPTS :: HListTypeSynonym s => s -> String hTIPSetTS :: HListTypeSynonym s => s -> String data HPresentRecAttr HPresentRecAttr :: HPresentRecAttr data HPresentTypedRecAttr HPresentTypedRecAttr :: HPresentTypedRecAttr instance Database.HaskRel.HFWTabulation.HListTypeSynonym Database.HaskRel.HFWTabulation.EmptyTS instance (Database.HaskRel.HFWTabulation.FWPPred a ~ flag, Database.HaskRel.HFWTabulation.FWPresent' flag a) => Database.HaskRel.HFWTabulation.FWPresent a instance GHC.Show.Show a => Database.HaskRel.HFWTabulation.FWPresent' Database.HaskRel.HFWTabulation.HFWOther a instance Database.HaskRel.HFWTabulation.FWPresent' Database.HaskRel.HFWTabulation.HFWString GHC.Base.String instance ([GHC.Base.String] ~ stringL, Database.HaskRel.HFWTabulation.FWPresent' (Database.HaskRel.HFWTabulation.FWPPred a) a) => Data.HList.FakePrelude.ApplyAB Database.HaskRel.HFWTabulation.HPresentRecAttr a stringL instance ([GHC.Base.String] ~ stringL, Database.HaskRel.HFWTabulation.FWPresent' (Database.HaskRel.HFWTabulation.FWPPred a) a) => Data.HList.FakePrelude.ApplyAB Database.HaskRel.HFWTabulation.HPresentTypedRecAttr a stringL instance (Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR r) [[GHC.Base.String]], Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentTypedRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR r) [[GHC.Base.String]], Data.Typeable.Internal.Typeable r, Data.HList.Record.RecordValues r) => Database.HaskRel.HFWTabulation.HFWPresent (Data.HList.Record.Record r) instance (Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR r) [[GHC.Base.String]], Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentTypedRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR r) [[GHC.Base.String]], Data.Typeable.Internal.Typeable r, Data.HList.Record.RecordValues r, Data.HList.Record.ShowComponents r) => Database.HaskRel.HFWTabulation.FWPresent' Database.HaskRel.HFWTabulation.HFWRec (Data.HList.Record.Record r) instance (Data.Typeable.Internal.Typeable a, Data.HList.Record.RecordValues a, Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR a) [[GHC.Base.String]], Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentTypedRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR a) [[GHC.Base.String]]) => Database.HaskRel.HFWTabulation.HFWPresent (Data.Set.Base.Set (Data.HList.Record.Record a)) instance (Data.Typeable.Internal.Typeable a, Data.HList.Record.RecordValues a, Data.HList.Record.ShowComponents a, Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR a) [[GHC.Base.String]], Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentTypedRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR a) [[GHC.Base.String]]) => Database.HaskRel.HFWTabulation.FWPresent' Database.HaskRel.HFWTabulation.HFWRecSet (Data.Set.Base.Set (Data.HList.Record.Record a)) -- | Predicates and aggregates useful to relational querying. These are not -- part of the relational algebra but are useful in relational queries in -- restriction predicates, and extension and summarization expressions. -- It also has great utility in non-relational queries, such as when -- performing aggregations. module Database.HaskRel.Support -- | Reverse predicate application. As "Data.Function.&", the reverse -- function application operator, but restricted to a boolean result. (&=) :: a -> (a -> Bool) -> Bool -- |
--   >>> plusminus 9 3 10
--   True
--   
plusminus :: (Ord a, Num a) => a -> a -> a -> Bool -- |
--   >>> 10 &= 9 +- 3
--   True
--   
(+-) :: (Ord a, Num a) => a -> a -> a -> Bool -- |
--   >>> 10 &= 9 ± 3
--   True
--   
--   >>> rPrint$ p ∣ (\[pun|weight|] -> weight &= 9 ± 3)
--   ┌─────┬───────┬───────┬────────┬────────┐
--   │ pno │ pName │ color │ weight │ city   │
--   ╞═════╪═══════╪═══════╪════════╪════════╡
--   │ P1  │ Nut   │ Red   │ 12 % 1 │ London │
--   │ P5  │ Cam   │ Blue  │ 12 % 1 │ Paris  │
--   └─────┴───────┴───────┴────────┴────────┘
--   
(±) :: (Ord a, Num a) => a -> a -> a -> Bool -- |
--   >>> 5 `between` (5,9)
--   True
--   
between :: Ord a => a -> (a, a) -> Bool -- |
--   >>> 5 &= 5 >=<= 9
--   True
--   
(>=<=) :: Ord a => a -> a -> a -> Bool -- |
--   >>> 5 &= 5 ≥≤ 9
--   True
--   
--   >>> rPrint$ p ∣ (\[pun|weight|] -> weight &= 11 ≥≤ 14)
--   ┌─────┬───────┬───────┬────────┬────────┐
--   │ pno │ pName │ color │ weight │ city   │
--   ╞═════╪═══════╪═══════╪════════╪════════╡
--   │ P1  │ Nut   │ Red   │ 12 % 1 │ London │
--   │ P4  │ Screw │ Red   │ 14 % 1 │ London │
--   │ P5  │ Cam   │ Blue  │ 12 % 1 │ Paris  │
--   └─────┴───────┴───────┴────────┴────────┘
--   
(≥≤) :: Ord a => a -> a -> a -> Bool -- | Between exclusive -- --
--   >>> 5 `xBetween` (5,9)
--   False
--   
xBetween :: Ord a => a -> (a, a) -> Bool -- |
--   >>> 5 &= 5 >< 9
--   False
--   
--   >>> rPrint$ p ∣ (\[pun|weight|] -> weight &= 11 >< 14)
--   ┌─────┬───────┬───────┬────────┬────────┐
--   │ pno │ pName │ color │ weight │ city   │
--   ╞═════╪═══════╪═══════╪════════╪════════╡
--   │ P1  │ Nut   │ Red   │ 12 % 1 │ London │
--   │ P5  │ Cam   │ Blue  │ 12 % 1 │ Paris  │
--   └─────┴───────┴───────┴────────┴────────┘
--   
(><) :: Ord a => a -> a -> a -> Bool -- |
--   >>> 5 &= 5 >=< 9
--   True
--   
(>=<) :: Ord a => a -> a -> a -> Bool -- |
--   >>> 5 &= 5 ≥< 9
--   True
--   
(≥<) :: Ord a => a -> a -> a -> Bool -- |
--   >>> 5 &= 5 ><= 9
--   False
--   
(><=) :: Ord a => a -> a -> a -> Bool -- |
--   >>> 5 &= 5 >≤ 9
--   False
--   
(>≤) :: Ord a => a -> a -> a -> Bool -- | Synonym for <= (≤) :: Ord a => a -> a -> Bool -- | Synonym for >= (≥) :: Ord a => a -> a -> Bool -- | Synonym for /= (≠) :: Eq a => a -> a -> Bool -- | Average of a list of values -- --
--   >>> let _qtys a = Label .=. a :: Tagged "qtys" Double
--   
--   >>> pt$ group sp (rHdr (pno,qty)) (_qtys . avg . agg qty)
--   ┌────────────────────┬───────────────┐
--   │ qtys :: Double     │ sno :: String │
--   ╞════════════════════╪═══════════════╡
--   │ 200.0              │ S3            │
--   │ 216.66666666666666 │ S1            │
--   │ 300.0              │ S4            │
--   │ 350.0              │ S2            │
--   └────────────────────┴───────────────┘
--   
-- -- Note the explicit type in the definition of _qtys; it is -- neccessary to provide a specific type for pt to format it as -- a table, even when an expression would otherwise be correct without -- this. The following would blow up if prefixed with "pt$": -- --
--   >>> group sp (rHdr (pno,qty)) ((qtys .=.) . avg . agg qty)
--   fromList [Record{qtys=200.0,sno="S3"},Record{qtys=216.66666666666666,sno="S1"},Record{qtys=300.0,sno="S4"},Record{qtys=350.0,sno="S2"}]
--   
avg :: (Fractional a, Real a1) => [a1] -> a -- | Minimum of several values, defaulting to the second argument if there -- are no elements. -- --
--   >>> pt$ group sp (rHdr (pno,qty)) ((qtys .=.) . (`minx` 0) . agg qty)
--   ┌─────────────────┬───────────────┐
--   │ qtys :: Integer │ sno :: String │
--   ╞═════════════════╪═══════════════╡
--   │ 100             │ S1            │
--   │ 200             │ S3            │
--   │ 200             │ S4            │
--   │ 300             │ S2            │
--   └─────────────────┴───────────────┘
--   
minx :: Ord a => [a] -> a -> a -- | Maximum of several values, defaulting to the second argument if there -- are no elements -- --
--   >>> pt$ group sp (rHdr (pno,qty)) ((qtys .=.) . (`maxx` 0) . agg qty)
--   ┌─────────────────┬───────────────┐
--   │ qtys :: Integer │ sno :: String │
--   ╞═════════════════╪═══════════════╡
--   │ 200             │ S3            │
--   │ 400             │ S1            │
--   │ 400             │ S2            │
--   │ 400             │ S4            │
--   └─────────────────┴───────────────┘
--   
maxx :: Ord a => [a] -> a -> a -- | Ordering functions. This is not of the relational model. module Database.HaskRel.Order -- | Takes any set (including that of a relation) and results in a list of -- the elements it consists of ordered by the given predicate orderBy :: Set a -> (a -> a -> Ordering) -> [a] -- | Takes any set (including that of a relation) and results in a list of -- the elements it consists of ordered on the given key function orderOn :: Ord b => Set a -> (a -> b) -> [a] newtype Asc a Asc :: a -> Asc a newtype Desc a Desc :: a -> Desc a instance GHC.Classes.Eq a => GHC.Classes.Eq (Database.HaskRel.Order.Desc a) instance GHC.Read.Read a => GHC.Read.Read (Database.HaskRel.Order.Desc a) instance GHC.Show.Show a => GHC.Show.Show (Database.HaskRel.Order.Desc a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Database.HaskRel.Order.Asc a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Database.HaskRel.Order.Asc a) instance GHC.Read.Read a => GHC.Read.Read (Database.HaskRel.Order.Asc a) instance GHC.Show.Show a => GHC.Show.Show (Database.HaskRel.Order.Asc a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Database.HaskRel.Order.Desc a) -- | Definition and presentation of relational objects in terms of Haskell -- and HList records, and certain implementation level supporting -- functions. -- -- Naming convention of the relational model is, to a degree, adopted to -- clarify how it is mirrored into Haskell. With these aliases in place -- the following are equivalent: -- --
--   >>> :t fromList [] :: Set (Record '[Tagged "sno" String, Tagged "status" Int])
--   
-- --
--   >>> :t relation [] :: Relation '[Attr "sno" String, Attr "status" Int]
--   
module Database.HaskRel.Relational.Definition -- | A shorthand for "attribute", and a synonym of Data.Tagged. type Attr = Tagged -- | A "tuple as defined by the relational model", synonym for -- Data.HList.Record. type RTuple = Record -- | A synonym for Set ( RTuple a ). type Relation a = Set (RTuple a) -- | A special Proxy for record labels, polykinded data Label (l :: k) :: k -> * Label :: Label -- | A helper to make the Proxy needed by hProjectByLabels, and similar -- functions which accept a list of kind [*]. -- -- For example: -- --
--   (rin,rout) = hProjectByLabels2 (Proxy :: Labels ["x","y"]) r
--   
-- -- behaves like -- --
--   rin = r .!. (Label :: Label "x") .*.
--         r .!. (Label :: Label "y") .*.
--         emptyRecord
--   
--   rout = r .-. (Label :: Label "x") .-. (Label :: Label "y")
--   
-- | Constructs an r-tuple from tagged values. Supports only 0 to 6-tuples. -- --
--   >>> pt$ rTuple (sno .=. "S1", sName .=. "Smith", status .=. (20::Integer), city .=. "London")
--   ┌───────────────┬─────────────────┬───────────────────┬────────────────┐
--   │ sno :: String │ sName :: String │ status :: Integer │ city :: String │
--   ├───────────────┼─────────────────┼───────────────────┼────────────────┤
--   │ S1            │ Smith           │ 20                │ London         │
--   └───────────────┴─────────────────┴───────────────────┴────────────────┘
--   
rTuple :: (HLabelSet (LabelsOf r), HTuple r t, HAllTaggedLV r) => t -> RTuple r -- | Constructs an r-tuple from a tuples of untagged values, where the -- labels and exact types are inferred from the context. Supports only 0 -- to 6-tuples. -- --
--   >>> pt$ ( rTuple' ("S1", "Smith", 20, "London") :: RTuple '[SNO, SName, Status, City] )
--   ...
--   
-- -- Result as for rTuple. rTuple' :: (RecordValues b, HTuple (RecordValuesR b) t, HMapAux HList TaggedFn (RecordValuesR b) b) => t -> RTuple b -- | Construct a relation value from a list of r-tuples of tagged values. -- Alias of fromList with a result restricted to Relation, -- with a name from relational theory. Supports only 0 to 6-tuples. -- --
--   >>> :{
--   pt$ relation [rTuple (sno .=. "S1", sName .=. "Smith", status .=. (20::Integer), city .=. "London"),
--                 rTuple (sno .=. "S2", sName .=. "Jones", status .=. (10::Integer), city .=. "Paris")]
--   :}
--   ┌───────────────┬─────────────────┬───────────────────┬────────────────┐
--   │ sno :: String │ sName :: String │ status :: Integer │ city :: String │
--   ╞═══════════════╪═════════════════╪═══════════════════╪════════════════╡
--   │ S1            │ Smith           │ 20                │ London         │
--   │ S2            │ Jones           │ 10                │ Paris          │
--   └───────────────┴─────────────────┴───────────────────┴────────────────┘
--   
relation :: (Ord a, a ~ Record b) => [a] -> Relation b -- | Construct a relation value from a list of tuples of untagged values, -- where the labels and exact types are inferred from the context. -- Supports only 0 to 6-tuples. -- --
--   >>> pt$ ( relation' [("S1", "Smith", 20, "London"), ("S2", "Jones", 10, "Paris")] :: Relation '[SNO, SName, Status, City] )
--   
-- -- Result as for relation. relation' :: (Ord (HList b), RecordValues b, HTuple (RecordValuesR b) t, HMapAux HList TaggedFn (RecordValuesR b) b) => [t] -> Relation b -- | Alias of Data.HList.HList.hFromTuple with a name that is more -- descriptive for the purpose of constructing Labels, which are -- employed as relational headings, from Haskell tuples of label values. -- When labels have been defined it permits expressing: -- --
--   >>> pt$ p `project` (undefined :: Labels '["pno","pName","color"])
--   
-- -- As: -- --
--   >>> pt$ p `project` (rHdr (pno,pName,color))
--   
-- -- Supports 0 to 6-tuples. rHdr :: HTuple v t => t -> HList v -- | Synonym of .=., for rename and nAs. as :: Label l -> v -> Tagged l v -- | N-adic constructor of as statements, using mkRecord . -- hFromTuple. Only supports 0 to 6-tuples. -- --
--   >>> let pnu = Label :: Label "pnu"
--   
--   >>> let colour = Label :: Label "colour"
--   
--   >>> :t nAs (pno `as` pnu, color `as` colour)
--   nAs (pno `as` pnu, color `as` colour)
--     :: Record '[Tagged "pno" (Label "pnu"), Tagged "color" (Label "colour")]
--   
nAs :: (HLabelSet (LabelsOf r), HTuple r t, HAllTaggedLV r) => t -> Record r -- | The nullary relation with an empty body -- --
--   >>> pt$ tableDum
--   ┌──┐
--   │  │
--   ╞══╡
--   └──┘
--   
--   >>> relation [] == tableDum
--   True
--   
tableDum :: Relation '[] -- | The nullary relation of cardinality one. -- --
--   >>> pt$ tableDee
--   ┌──┐
--   │  │
--   ╞══╡
--   │  │
--   └──┘
--   
--   >>> relation [rTuple ()] == tableDee
--   True
--   
--   >>> relation' [()] == tableDee
--   True
--   
tableDee :: Relation '[] -- | The empty set without an explicit type. In a relational context this -- is a relation with an empty body and no defined heading. -- --
--   >>> relation [rTuple (sno .=. "S1", status .=. 5)] == empty
--   False
--   
-- -- Note how the example for tableDum won't work for empty -- and vice-versa. empty :: Set a -- | Order-agnostic equality operation, which is neccessary for comparison -- correct for r-tuples. unordRecEq :: (Eq (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => RTuple l -> RTuple r -> Bool -- | Gives the body of a relation as a list. This will untag the values. bodyAsList :: RecordValues r => Relation r -> [HList (RecordValuesR r)] -- | Rearrange a set of HList records to context. From the perspective of -- relational theory this is a presentation function. relRearrange :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation r -> Relation l -- | Rearrange a set of HList records to the order of a set given by an -- argument. The value of the second argument will be ignored. From the -- perspective of relational theory this is a presentation function. relRearrange' :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation r -> Relation l -> Relation l -- | HaskRel type synonyms data HaskRelTS HaskRelTS :: HaskRelTS -- | Type synoyms used when building the table header with type names class HListTypeSynonym s -- | Prints a tabular representation of an r-tuple or relation. rPrint :: HFWPresent r => r -> IO () -- | Prints a tabular representation of an r-tuple or relation, with type -- information. rPrintTyped :: HFWPresent r => r -> IO () -- | Synonym of rPrint. p :: HFWPresent r => r -> IO () -- | Synonym of rPrintTyped. pt :: HFWPresent r => r -> IO () -- | Specialization of Database.HaskRel.HFWTabulation.showHTypeTS -- that employs HaskRel specific type-synonyms. rShowType :: TypeRep -> String -- | Shows a tabular representation of a relation. showRelTab :: (Typeable a, RecordValues a, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]]) => Relation a -> String instance forall (k :: BOX) (a :: k). Data.HList.HList.HTuple '[Data.HList.FakePrelude.Label a] (Data.HList.FakePrelude.Label a) instance forall (k :: BOX) (a :: k) a'. Data.HList.HList.HTuple '[Data.Tagged.Tagged a a'] (Data.Tagged.Tagged a a') instance Database.HaskRel.HFWTabulation.HListTypeSynonym Database.HaskRel.Relational.Definition.HaskRelTS -- | Relation variable definition, along with IO level support functions. module Database.HaskRel.Relational.Variable -- | Relation variable reference. This type has a phantom type variable, -- which generally calls for the type to be explicity specified: -- --
--   s = Relvar "SuppliersPartsDB/S.rv" :: Relvar '[SNO, SName, Status, City]
--   
data Relvar (a :: [*]) Relvar :: FilePath -> Relvar [relvarPath] :: Relvar -> FilePath -- | Gives the type a relvar results in. Note that the value this results -- in will always be undefined. relvarType :: Relvar a -> Relation a -- | Reads a relation value from a string containing HLists of unpacked -- attribues. -- --
--   >>> pt$ ( readRel "H[\"S1\",10],H[\"S2\",50]" :: Relation '[SNO,Status])
--   ┌───────────────┬───────────────────┐
--   │ sno :: String │ status :: Integer │
--   ╞═══════════════╪═══════════════════╡
--   │ S1            │ 10                │
--   │ S2            │ 50                │
--   └───────────────┴───────────────────┘
--   
readRel :: (Ord (HList b), Read (HList (RecordValuesR b)), RecordValues b, HMapAux HList TaggedFn (RecordValuesR b) b) => String -> Relation b -- | Read a relation variable from the file referenced by the first -- argument readRelvar :: (Ord (HList b), Read (HList (RecordValuesR b)), RecordValues b, HMapAux HList TaggedFn (RecordValuesR b) b) => Relvar b -> IO (Relation b) -- | Converts a list of HLists into a relation value. hListsToRel :: (Ord (HList b), RecordValues b, HMapAux HList TaggedFn (RecordValuesR b) b) => [HList (RecordValuesR b)] -> Relation b -- | Writes a body of a relvar to a given file writeRelvarBody :: Show r => FilePath -> r -> IO () -- | Writes a body of a relvar to a given relvar file reference writeRelvarBody' :: Show r => Relvar rv -> r -> IO () -- | Prints a relation as a list without the outer brackets. showRelStr :: (Show (HList (RecordValuesR r)), RecordValues r) => Relation r -> String instance Data.Typeable.Internal.Typeable a => GHC.Show.Show (Database.HaskRel.Relational.Variable.Relvar a) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.Typeable.Internal.Typeable b, Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b, Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentTypedRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR b) [[GHC.Base.String]], Data.HList.HList.HFoldr (Data.HList.HList.Mapcar Database.HaskRel.HFWTabulation.HPresentRecAttr) [[GHC.Base.String]] (Data.HList.Record.RecordValuesR b) [[GHC.Base.String]]) => Database.HaskRel.HFWTabulation.HFWPresent (Database.HaskRel.Relational.Variable.Relvar b) -- | Relational algebra based on HList records. -- -- It is important to note that, in order to build a straight forward -- foundation, this module defines pure functions, viz. they only operate -- upon relational values, not relvars or the result of -- expressions involving relvars. See -- Database.HaskRel.Relational.Expression for functions that -- function as conveyed by the relational model, which are the ones that -- are intended to be used directly. -- -- All the examples in Database.HaskRel.Relational.Expression are -- defined in terms of the relvars s, p and sp; to run the examples in -- that module with the functions of this module one can use the relation -- values s', p' and sp' instead. The script examples/algebraExample.sh -- starts a GHCi session with the imports and pragmas required to run -- these examples. module Database.HaskRel.Relational.Algebra -- | Rename multiple attributes of a relation. -- --
--   >>> let pnu = Label :: Label "pnu"
--   
--   >>> let colour = Label :: Label "colour"
--   
--   >>> rPrint$ p' `rename` nAs( pno `as` pnu, color `as` colour )
--   ┌─────┬───────┬────────┬────────┬────────┐
--   │ pnu │ pName │ colour │ weight │ city   │
--   ╞═════╪═══════╪════════╪════════╪════════╡
--   │ P1  │ Nut   │ Red    │ 12 % 1 │ London │
--   ...
--   
rename :: (Ord (HList r), HLabelSet (LabelsOf r), HMapAux HList (Relabel tr) a r, SameLength' r a, SameLength' a r, HAllTaggedLV r) => Relation a -> tr -> Relation r -- | Extends the given relation with the r-tuple resulting from the second -- argument. Existing attributes with the same name will be replaced. -- -- See extend. extend :: (Ord (HList (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r r'1)), HDeleteLabels (LabelsOf r) r' r'1, HAppendList r r'1, HAllTaggedLV (HAppendListR r r'1)) => Relation r' -> (Record r' -> Record r) -> Relation (HAppendListR r r'1) -- | Restricts the given relation according to the given predicate. Note -- that this is the well known WHERE operator of both SQL and -- Tutorial D, but since "where" is a reserved keyword in Haskell it is -- named "restrict". -- -- See restrict. restrict :: Set a -> (a -> Bool) -> Set a -- | Projects the given relation on the given heading. -- -- See project. project :: (Ord (HList a), HLabelSet (LabelsOf a), H2ProjectByLabels ls t a b, HAllTaggedLV a) => Relation t -> proxy ls -> Relation a -- | Projects the given relation on the heading of said given relation -- minus the given heading. -- -- See projectAllBut. projectAllBut :: (Ord (HList r'), HDeleteLabels ks r r') => Relation r -> proxy ks -> Relation r' -- | Performs a natural join of the two given relations. -- -- See naturalJoin. naturalJoin :: (Eq (HList l), Ord (HList (HAppendListR t1 t2)), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf r), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, HAppendList t1 t2, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR t1 t2)) => Relation t1 -> Relation t -> Relation (HAppendListR t1 t2) -- | Alias of naturalJoin. -- -- See nJoin. nJoin :: (Eq (HList l), Ord (HList (HAppendListR t1 t2)), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf r), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, HAppendList t1 t2, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR t1 t2)) => Relation t1 -> Relation t -> Relation (HAppendListR t1 t2) -- | The cartesian product of two relations. A specialized natural join; -- the natural join between two relations with disjoint headings. -- -- See times. times :: (HRLabelSet (HAppendListR t r), Eq (HList l), Ord (HList (HAppendListR t1 t2)), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf r), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, HAppendList t1 t2, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR t1 t2)) => Relation t1 -> Relation t -> Relation (HAppendListR t1 t2) -- | Performs a semi-join of the first given relation against the second -- given relation. -- -- See matching. matching :: (Eq (HList l), Ord (HList t), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b, H2ProjectByLabels (LabelsOf l1) t r b1, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r) => Relation t -> Relation l1 -> Relation t -- | Alias of matching. See semiJoin. semiJoin :: (Eq (HList l), Ord (HList t), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b, H2ProjectByLabels (LabelsOf l1) t r b1, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r) => Relation t -> Relation l1 -> Relation t -- | Performs a semi-difference of the first given relation against the -- second given relation. -- -- Aka. antijoin: -- -- Also known, a trifle inappropriately, as antijoin. -- -- -- -- See notMatching. notMatching :: (Eq (HList l), Ord (HList t), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b, H2ProjectByLabels (LabelsOf l1) t r b1, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r) => Relation t -> Relation l1 -> Relation t -- | Alias of notMatching. See semiDiff. semiDiff :: (Eq (HList l), Ord (HList t), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b, H2ProjectByLabels (LabelsOf l1) t r b1, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r) => Relation t -> Relation l1 -> Relation t -- | Performs a union of the given relations. -- -- See union. union :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation l -> Relation r -> Relation l -- | Performs a disjoint union between the two relvars. This is a union of -- disjoint relations, where a runtime error is raised if the operands -- are not disjoint. -- -- See dUnion. dUnion :: (Ord (HList a), Typeable a, RecordValues a, HRearrange3 (LabelsOf a) r a, HLabelSet (LabelsOf a), HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]], SameLength' a r, SameLength' r a, SameLength' r (LabelsOf a), SameLength' (LabelsOf a) r) => Relation a -> Relation r -> Relation a -- | The intersection of two relations. -- -- Note how the name is different from Data.Set, where the comparable -- function is named "intersection". This is due to it being referred to -- as "intersect" in material describing the relational model; -- specifically named "INTERSECT" in Tutorial D. -- -- See intersect. intersect :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation l -> Relation r -> Relation l -- | The difference of two relations. -- -- The "minus" term is used in material describing relational theory; -- specifically Tutorial D names the operator "MINUS". -- -- See minus. minus :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation l -> Relation r -> Relation l -- | Exclusive union, aka. symmetric difference. -- -- See xUnion. xUnion :: (Ord (HList r1), HRearrange3 (LabelsOf r1) r r1, HRearrange3 (LabelsOf r1) r1 r1, HLabelSet (LabelsOf r1), SameLength' r r1, SameLength' r (LabelsOf r1), SameLength' r1 r, SameLength' r1 r1, SameLength' r1 (LabelsOf r1), SameLength' (LabelsOf r1) r, SameLength' (LabelsOf r1) r1) => Relation r1 -> Relation r -> Relation r1 -- | Groups the given attributes of the given relation into a given new -- relation valued attribute. -- -- As the Tutorial D GROUP operator, not SQL GROUP BY. -- -- See group. group :: (Eq (HList l), Ord v, Ord (HList l1), Ord (HList r'), HLabelSet (LabelsOf l), HLabelSet (Label t : LabelsOf l1), HDeleteLabels ks r l1, HDeleteLabels (LabelsOf l1) r r', H2ProjectByLabels (LabelsOf l) r l b, H2ProjectByLabels (LabelsOf r) l1 l b1, HAllTaggedLV l1, HAllTaggedLV l) => Relation r -> proxy ks -> (Relation r' -> Tagged t v) -> Relation (Tagged t v : l1) -- | Groups the given relation on all but the given attributes into a given -- new attribute. -- -- See groupAllBut. groupAllBut :: (Eq (HList l), Ord v, Ord (HList l1), Ord (HList r'), HLabelSet (LabelsOf l), HLabelSet (LabelsOf l1), HLabelSet (Label t : LabelsOf l1), HDeleteLabels (LabelsOf l1) t1 r', H2ProjectByLabels ls t1 l1 b2, H2ProjectByLabels (LabelsOf l) t1 l b, H2ProjectByLabels (LabelsOf t1) l1 l b1, HAllTaggedLV l1, HAllTaggedLV l) => Relation t1 -> proxy ls -> (Relation r' -> Tagged t v) -> Relation (Tagged t v : l1) -- | Ungroups the given attribute of the given relation. -- --
--   >>> let pq = (Label :: Label "pq")
--   
--   >>> sp' == ungroup ( group sp' (rHdr (pno,qty)) (pq .=.)) pq
--   True
--   
-- -- Note the difference to ungroup, which requires rEq for -- relational comparison. ungroup :: (Eq (HList l), Ord (HList (HAppendListR t1 t2)), HasField l1 (Record v) (Relation t), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf r), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, H2ProjectByLabels '[Label l1] v t3 t1, HAppendList t1 t2, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR t1 t2)) => Relation v -> Label l1 -> Relation (HAppendListR t1 t2) -- | Summarize. -- -- See summarize. summarize :: (Eq (HList l), Ord (HList r'), Ord (HList r'2), Ord (HList (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r' r)), HLabelSet (LabelsOf l), HDeleteLabels ks r2 r', HDeleteLabels (LabelsOf r) r' r'1, HDeleteLabels (LabelsOf r') r1 r'2, H2ProjectByLabels (LabelsOf l) r1 l b, H2ProjectByLabels (LabelsOf r1) r' l b1, HAppendList r r'1, HAllTaggedLV l, HAllTaggedLV (HAppendListR r r'1), HAllTaggedLV (HAppendListR r' r)) => Relation r1 -> Relation r2 -> proxy ks -> (Relation r'2 -> Record r) -> Relation (HAppendListR r r'1) -- | Performs a natural join between two relations with intersecting -- headings. A specialized natural join. -- -- A join upon relations r1, r2 where the intersection of the heading of -- r1 and of r2 is not empty; the headings are not disjoint. This is the -- complement of times that together with it forms a natural join; -- all that would be disallowed for times is allowed here and -- vice-versa. The name is what I quickly settled on, suggestions for a -- better one would be welcome. (Attribute-Intersecting Natural Join is -- another candidate.) -- -- This function doesn't have a specific identity value, although it -- holds that r `interJoin` r = r -- -- See interJoin. interJoin :: (HTIntersect (LabelsOf r) (LabelsOf t) i, NotEmpty i, Eq (HList l), Ord (HList (HAppendListR t1 t2)), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf r), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, HAppendList t1 t2, SameLength' l r, SameLength' r l, SameLength' r (LabelsOf l), SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR t1 t2)) => Relation t1 -> Relation t -> Relation (HAppendListR t1 t2) -- | Alias of interJoin. See iJoin. iJoin :: (Eq (HList l), Ord (HList (HAppendListR t1 t2)), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), HLabelSet (LabelsOf r), HLabelSet (LabelsOf t2), HLabelSet (LabelsOf (HAppendListR t1 t2)), H2ProjectByLabels (LabelsOf t) t1 r b, H2ProjectByLabels (LabelsOf t1) t l t2, HTIntersect (LabelsOf r) (LabelsOf t) i, HAppendList t1 t2, SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV r, HAllTaggedLV l, HAllTaggedLV (HAppendListR t1 t2), NotEmpty i) => Relation t1 -> Relation t -> Relation (HAppendListR t1 t2) -- | Disjoint extension. Extends the given relation with the result of the -- second argument, as extend, but without deleting any that -- exist. -- -- See dExtend. dExtend :: (Ord (HList (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r r'1)), HDeleteLabels (LabelsOf r) r' r'1, HAppendList r r'1, HAllTaggedLV (HAppendListR r r'1), HRLabelSet (HAppendListR r' r)) => Relation r' -> (Record r' -> Record r) -> Relation (HAppendListR r r'1) -- | Auto-summarization. A specialization of summarize with the same -- source and destination relation. -- -- See aSummarize. aSummarize :: (Eq (HList l), Ord (HList r'), Ord (HList r'2), Ord (HList (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r r'1)), HLabelSet (LabelsOf (HAppendListR r' r)), HLabelSet (LabelsOf l), HDeleteLabels ks r1 r', HDeleteLabels (LabelsOf r) r' r'1, HDeleteLabels (LabelsOf r') r1 r'2, H2ProjectByLabels (LabelsOf l) r1 l b, H2ProjectByLabels (LabelsOf r1) r' l b1, HAppendList r r'1, HAllTaggedLV l, HAllTaggedLV (HAppendListR r r'1), HAllTaggedLV (HAppendListR r' r)) => Relation r1 -> proxy ks -> (Relation r'2 -> Record r) -> Relation (HAppendListR r r'1) -- | Extends the first given relation with an attribute resulting from -- imaging each tuple of said relation against the second given relation. -- This gives a superset of the information given by SQL RIGHT OUTER -- JOIN. -- -- See imageExtendL. imageExtendL :: (Eq (HList l), Ord (HList l1), Ord (HList r'), HLabelSet (LabelsOf l), HLabelSet (Label t : LabelsOf l1), HDeleteLabels (LabelsOf l1) r r', H2ProjectByLabels (LabelsOf l) r l b, H2ProjectByLabels (LabelsOf r) l1 l b1, HAllTaggedLV l1, HAllTaggedLV l) => Set (Record l1) -> Relation r -> Label t -> Set (Record (Tagged t (Relation r') : l1)) -- | The difference of two relations. This differs from minus in -- that the attribute order of the second argument takes precedence, -- which is neccessary to swap precedence since minus is -- non-commutative. This function is as such equal to minus as far -- as relational theory is concerned, the difference is on a lower level -- of abstraction. minus_ :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation r -> Relation l -> Relation l -- | Extends the given relation with the attribute resulting from the -- second argument. If an attribute with the same name exists then it -- will be replaced. This allows for the function of the second argument -- to be simpler. -- -- See extendA. extendA :: (Ord (HExtendR (Tagged l e) (r v')), HExtend (Tagged l e) (r v'), HDeleteAtLabel r l v v') => Set (r v) -> (r v -> Tagged l e) -> Set (HExtendR (Tagged l e) (r v')) -- | Disjoint extension of a single attribute. Extends the given relation -- with the result of the second argument, as extend, but without -- deleting any that exist. l cannot already have any attribute -- e. -- -- See dExtendA. dExtendA :: (Ord (HExtendR e l), HExtend e l) => Set l -> (l -> e) -> Set (HExtendR e l) -- | Renames a single attribute. See renameA renameA :: (Ord (HExtendR (Tagged l1 v1) (r v')), HasField l (r v) v1, HExtend (Tagged l1 v1) (r v'), HDeleteAtLabel r l v v') => Set (r v) -> Tagged l (Label l1) -> Set (HExtendR (Tagged l1 v1) (r v')) -- | Tests whether the second argument is a proper subset of the first. -- -- See isProperSubsetOf. isProperSubsetOf :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation l -> Relation r -> Bool -- | Tests whether the second argument is a subset of the first. -- -- See isSubsetOf. isSubsetOf :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation l -> Relation r -> Bool -- | The image of a relation corresponding to an r-tuple. -- -- An application of the first argument only, an r-tuple, to this -- function yields what is known as the !! operator in Tutorial -- D. -- --
--   >>> let qtySum = Label::Label "qtySum"
--   
--   >>> :{
--       rPrint$ s'
--               `project` (rHdr (sno))
--               `extendA` (\ (image -> ii) ->
--                               qtySum .=.
--                                   ( sum $ aggU $ ii ( sp' `project` (rHdr (sno,qty)) ) ) )
--    :}
--   
-- -- See image. image :: (Eq (HList l), Ord (HList r'), HLabelSet (LabelsOf l), HDeleteLabels (LabelsOf l1) r r', H2ProjectByLabels (LabelsOf l) r l b, H2ProjectByLabels (LabelsOf r) l1 l b1, HAllTaggedLV l) => Record l1 -> Relation r -> Relation r' -- | Gives the cardinality of the argument. count :: Set a -> Int -- | Gives whether the given argument is empty or not. isEmpty :: Set a -> Bool -- | Right-fold of an attribute of a relation (although a "right" fold -- doesn't make sense in the context of the relational model). Note that -- the value of the third argument, att, is not used and may be -- "undefined". -- -- See rafoldr. rafoldr :: (Foldable t, HasField l a b1) => (b1 -> b -> b) -> b -> Label l -> t a -> b -- | Right-fold of the attribute of an unary relation. -- -- See rafoldrU. rafoldrU :: Foldable t => (b1 -> b -> b) -> b -> t (Record '[Tagged t1 b1]) -> b -- | Attribute value aggregation, a specialization of rafoldr that -- aggregates the values of a single attribute into a list of the values -- the attribute type wraps. -- -- Note that the value of the first argument, att, is not used -- and may be "undefined". -- --
--   >>> sum $ agg qty sp'
--   3100
--   
-- -- See agg. agg :: (Foldable t, HasField l a a1) => Label l -> t a -> [a1] -- | Aggregation of the single attribute of an unary relation. A -- specialization of agg, and thus in turn of rafoldr, that -- aggregates the single attribute of an unary relation, without -- requiring the name of that attribute. -- --
--   >>> sum $ aggU $ sp' `project` (rHdr (qty))
--   1000
--   
-- -- See aggU. aggU :: Foldable t => t (Record '[Tagged t1 a]) -> [a] -- | Rearrange a set of HList records to context. From the perspective of -- relational theory this is a presentation function. relRearrange :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r) => Relation r -> Relation l -- | Failure class restricting a type-level operation to a non-empty -- result. class NotEmpty (l :: [*]) data Relabel tr instance forall (k :: BOX) (k1 :: BOX) r (l :: k1) a b (v :: GHC.Base.Maybe *) (dl :: k). (Data.HList.Record.HasFieldM l r v, Data.HList.FakePrelude.Label dl ~ Data.HList.Record.DemoteMaybe (Data.HList.FakePrelude.Label l) v, b ~ Data.Tagged.Tagged dl a) => Data.HList.FakePrelude.ApplyAB (Database.HaskRel.Relational.Algebra.Relabel r) (Data.Tagged.Tagged l a) b instance Database.HaskRel.Relational.Algebra.NotEmpty l instance Data.HList.FakePrelude.Fail Database.HaskRel.Relational.Algebra.IsEmpty => Database.HaskRel.Relational.Algebra.NotEmpty '[] -- | Relational assignment and specalizations thereof. As with -- Database.HaskRel.Relational.Algebra this does not support -- relational expressions building on relvars, but defers that to -- Database.HaskRel.Relational.Expression. module Database.HaskRel.Relational.Assignment -- | Writes a relation value to a relvar file, replacing the existing -- value. assign :: (Ord (HList a), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) r a, HLabelSet (LabelsOf a), SameLength' r a, SameLength' r (LabelsOf a), SameLength' a r, SameLength' (LabelsOf a) r) => Relvar a -> Relation r -> IO () -- | Inserts a relation into a relvar. This differs from SQL's INSERT; the -- relvar is updated to the union of the relvar and the relation value -- given as arguments. -- -- See insert. insert :: (Ord (HList a), Read (HList (RecordValuesR a)), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) r a, HLabelSet (LabelsOf a), HMapAux HList TaggedFn (RecordValuesR a) a, SameLength' r a, SameLength' r (LabelsOf a), SameLength' a r, SameLength' (LabelsOf a) r) => Relvar a -> Relation r -> IO () -- | Disjoint insert. Closer to SQL INSERT, except that this will never -- insert a duplicate tuple. -- -- See dInsert. dInsert :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR r)), Typeable t, RecordValues r, RecordValues t, HRearrange3 (LabelsOf t) r t, HLabelSet (LabelsOf t), HMapAux HList TaggedFn (RecordValuesR t) t, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR t) [[String]], SameLength' r t, SameLength' r (LabelsOf t), SameLength' t r, SameLength' (LabelsOf t) r) => Relvar t -> Relation r -> IO () -- | Updates tuples of a relvar that match the given predicate. As SQL -- UPDATE. -- --
--   >>> update sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> _qty ( qty - 25 ) .*. emptyRecord)
--   Updated 5 of 12 tuples in SuppliersPartsDB/SP.rv
--   *SuppliersPartsExample> rPrint$ sp
--   ┌─────┬─────┬─────┐
--   │ sno │ pno │ qty │
--   ╞═════╪═════╪═════╡
--   │ S1  │ P1  │ 300 │
--   │ S1  │ P2  │ 175 │
--   │ S1  │ P3  │ 375 │
--   │ S1  │ P4  │ 200 │
--   ...
--   
-- -- Note how the cardinality of the relvar will be equal or lower after an -- update: -- --
--   >>> assign sp sp'
--   Value assigned to SuppliersPartsDB/SP.rv
--   
--   >>> count sp
--   12
--   
--   >>> update sp (\[pun|pno|] -> pno == "P1" || pno == "P2" || pno == "P3") (\_ -> _pno "P1" .*. _qty 50 .*. emptyRecord)
--   Updated 7 of 12 tuples in SuppliersPartsDB/SP.rv
--   
--   >>> count sp
--   9
--   
update :: (Ord (HList a), Read (HList (RecordValuesR a)), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) (HAppendListR r r'2) a, HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)), HDeleteLabels (LabelsOf r) a r'2, HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2, SameLength' a (HAppendListR r r'2), SameLength' (LabelsOf a) (HAppendListR r r'2), SameLength' (HAppendListR r r'2) a, SameLength' (HAppendListR r r'2) (LabelsOf a), HAllTaggedLV (HAppendListR r r'2)) => Relvar a -> (Record a -> Bool) -> (Record a -> Record r) -> IO () -- | Updates tuples of a relvar that match the given predicate. -- -- In SQL and Tutorial D both the predicate of UPDATE is an -- optional clause, but optional clauses isn't idiomatic Haskell, hence -- this separate updateAll function. -- --
--   >>> updateAll sp (\ [pun|qty pno|] -> _qty ( qty - 25 ) .*. _pno ( pno ++ "X" ) .*. emptyRecord)
--   Updated 12 tuples in SuppliersPartsDB/SP.rv
--   *SuppliersPartsExample> pt sp
--   ┌───────────────┬───────────────┬────────────────┐
--   │ sno :: String │ pno :: String │ qty :: Integer │
--   ╞═══════════════╪═══════════════╪════════════════╡
--   │ S1            │ P1X           │ 275            │
--   ...
--   
updateAll :: (Ord (HList a), Read (HList (RecordValuesR a)), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) (HAppendListR r r'2) a, HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)), HDeleteLabels (LabelsOf r) a r'2, HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2, SameLength' a (HAppendListR r r'2), SameLength' (LabelsOf a) (HAppendListR r r'2), SameLength' (HAppendListR r r'2) a, SameLength' (HAppendListR r r'2) (LabelsOf a), HAllTaggedLV (HAppendListR r r'2)) => Relvar a -> (Record a -> Record r) -> IO () -- | Deletes a specified subset of a relvar. Note that this is not SQL -- DELETE, but instead a generalization thereof. -- -- See delete. delete :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), RecordValues t, HMapAux HList TaggedFn (RecordValuesR t) t) => Relvar t -> Relation t -> IO () -- | Performs an inclusive delete against a relvar. Also not SQL DELETE. -- This will fail if the second argument is not a subset of the relation -- value identified by the relation variable reference. -- -- See iDelete. iDelete :: (Ord (HList a), Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), Typeable a, RecordValues a, RecordValues t, HRearrange3 (LabelsOf t) a t, HRearrange3 (LabelsOf a) t a, HLabelSet (LabelsOf t), HLabelSet (LabelsOf a), HMapAux HList TaggedFn (RecordValuesR t) t, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]], SameLength' a t, SameLength' a (LabelsOf t), SameLength' t a, SameLength' t (LabelsOf a), SameLength' (LabelsOf t) a, SameLength' (LabelsOf a) t) => Relvar t -> Relation a -> IO () -- | Delete by predicate, as SQL DELETE. -- --
--   >>> let newProd = relation [rTuple (pno .=. "P7", pName .=. "Baloon", color .=. "Red", weight .=. (-5 :: Rational), city .=. "Berlin")]
--   
--   >>> insert p newProd
--   Inserted 1 of 1 tuples into SuppliersPartsDB/P.rv
--   
--   >>> deleteP p (\ [pun|pno|] -> pno == "P7" )
--   Deleted 1 tuples from SuppliersPartsDB/P.rv
--   
deleteP :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), RecordValues t, HMapAux HList TaggedFn (RecordValuesR t) t) => Relvar t -> (RTuple t -> Bool) -> IO () -- | Updates all tuples of a relvar. The second argument is a function that -- results in an attribute, making for a simpler function than for -- update. -- --
--   >>> updateA sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> _qty $ qty - 25)
--   Updated 5 of 12 tuples in SuppliersPartsDB/SP.rv
--   
updateA :: (Ord (HList r), Read (HList (RecordValuesR r)), Show (HList (RecordValuesR r)), HUpdateAtLabel2 k l v r r, RecordValues r, HasField k l (Record r) v, HMapAux HList TaggedFn (RecordValuesR r) r, SameLength' * * r r) => Relvar r -> (Record r -> Bool) -> (Record r -> Tagged k l v) -> IO () -- | Updates all tuples of a relvar. The second argument is a function that -- results in an attribute, making for a simpler function than for -- updateAll. -- --
--   >>> updateAllA sp (\ [pun|qty|] -> _qty $ qty - 50)
--   Updated 12 tuples in SuppliersPartsDB/SP.rv
--   
--   >>> rPrint$ sp
--   ┌───────────────┬───────────────┬────────────────┐
--   │ sno :: String │ pno :: String │ qty :: Integer │
--   ╞═══════════════╪═══════════════╪════════════════╡
--   │ S1            │ P1            │ 250            │
--   ...
--   
updateAllA :: (Ord (HList r), Read (HList (RecordValuesR r)), Show (HList (RecordValuesR r)), HUpdateAtLabel2 k l v r r, RecordValues r, HasField k l (Record r) v, HMapAux HList TaggedFn (RecordValuesR r) r, SameLength' * * r r) => Relvar r -> (Record r -> Tagged k l v) -> IO () -- | Database.HaskRel.Relational.Algebra and -- Database.HaskRel.Relational.Assignment defines the functions of -- the relational algebra and relational assignment, but in order to keep -- pertinent concerns separated it only defines functions for relational -- operations upon values, not relation variables. This module redefines -- those functions, generalizing them such that they operate upon -- relation values, relation variables and relational IO (relational -- expressions that build upon relvars), and also adds HFWPresent -- instances for relational IO. -- -- Running "examples/suppliersPartsExample.sh" starts a GHCi session -- where these examples can be run. -- -- Note that certain browsers and operating system combinations result in -- incorrect display of the horizontal lines of tables. module Database.HaskRel.Relational.Expression -- | The class of relational monadic operators class MonOp a where type family MonOpRes a res :: * type family MonOpArg a :: * MonOpRes a res = IO res -- | Unary relational function application. monOp :: MonOp a => (MonOpArg a -> res) -> a -> MonOpRes a res -- | Rename given attributes of a relation. -- --
--   >>> let pnu = Label :: Label "pnu"
--   
--   >>> let colour = Label :: Label "colour"
--   
--   >>> rPrint$ p `rename` nAs( pno `as` pnu, color `as` colour )
--   ┌─────┬───────┬────────┬────────┬────────┐
--   │ pnu │ pName │ colour │ weight │ city   │
--   ╞═════╪═══════╪════════╪════════╪════════╡
--   │ P1  │ Nut   │ Red    │ 12 % 1 │ London │
--   ...
--   
-- -- Note that due to an implementation disorder this always results in an -- IO operation, even on values. This is not an intentional limit and -- will hopefully be removed in the future. If this is not acceptable -- (for instance inside extend and restrict functions), -- then one has to rely on renameA, which renames a single -- attribute. rename :: (Ord (HList res), HLabelSet [*] (LabelsOf res), HMapAux HList (Relabel tr) a1 res, SameLength' * * res a1, SameLength' * * a1 res, HAllTaggedLV res, MonOp' a, (~) * (MonOpArg' a) (Set (RTuple a1))) => a -> tr -> IO (Relation res) -- | Extends the given relation with the r-tuple resulting from the second -- argument. Existing attributes with the same name will be replaced. -- -- The simplest form (aside from a no-op), extend with one attribute: -- --
--   >>> rPrint$ extend p (\ [pun|weight|] -> (Label :: Label "gmwt") .=. weight * 454 .*. emptyRecord )
--   ┌──────────┬─────┬───────┬───────┬────────┬────────┐
--   │ gmwt     │ pno │ pName │ color │ weight │ city   │
--   ╞══════════╪═════╪═══════╪═══════╪════════╪════════╡
--   │ 5448 % 1 │ P1  │ Nut   │ Red   │ 12 % 1 │ London │
--   ...
--   │ 8626 % 1 │ P6  │ Cog   │ Red   │ 19 % 1 │ London │
--   └──────────┴─────┴───────┴───────┴────────┴────────┘
--   
-- -- When replacing an attribute with extend one must take care not to -- cause a naming collision. Using pattern matching with case ... of -- ... one can pass values from one context to another with Haskell -- tuples, and reuse variable names, although this does require some -- duplication. It is also possible to use pun to build the -- output, instead of .*. and emptyRecord. Add one -- attribute, replace another: -- --
--   >>> rPrint$ extend p (\[pun|weight color|] -> case (weight + 10, color ++ "-ish") of (weight, altColor) -> [pun|weight altColor|])
--   ┌────────┬───────────┬─────┬───────┬───────┬────────┐
--   │ weight │ altColor  │ pno │ pName │ color │ city   │
--   ╞════════╪═══════════╪═════╪═══════╪═══════╪════════╡
--   │ 22 % 1 │ Blue-ish  │ P5  │ Cam   │ Blue  │ Paris  │
--   ...
--   │ 29 % 1 │ Red-ish   │ P6  │ Cog   │ Red   │ London │
--   └────────┴───────────┴─────┴───────┴───────┴────────┘
--   
-- -- Lining this up with the EXTEND operator of Tutorial D, we can -- imagine case (a, b) of (a', b') as a form of { a' := a -- , b' := b } (though we can hardly equate them), while -- pun is needed to unpack and pack this from and to the -- r-tuples. -- -- If no attributes are replaced then the cardinality of the result will -- be equal to the cardinality of the argument, if an attribute is -- replaced then the cardinality of the result will be equal or lower -- than that of the argument. -- --
--   >>> count sp
--   12
--   
--   >>> count $ sp `extend` (\_ -> sno .=. "S0" .*. pno .=. "P0" .*. emptyRecord)
--   4
--   
-- -- It is also notable that since HaskRel is not based on SQL but on -- relational theory as defined by Chris Date et al. today, and -- explicitly does not have support for nulls and outer joins (as -- specified in [1] chapter 4), extend is employed to assemble -- the information SQL assembles with OUTER JOIN. The following -- command (a variant of the first query on [1] page 154) gives a result -- that includes the information given by SQL RIGHT OUTER JOIN: -- --
--   >>> :{
--   do sp' <- readRelvar sp
--      rPrint$ extend s (\ (image -> ii) -> pq .=. ii sp' .*. emptyRecord)
--   :}
--   ┌───────────────┬─────┬───────┬────────┬────────┐
--   │ pq            │ sno │ sName │ status │ city   │
--   ╞═══════════════╪═════╪═══════╪════════╪════════╡
--   │ ┌─────┬─────┐ │ S5  │ Adams │ 30     │ Athens │
--   │ │ pno │ qty │ │     │       │        │        │
--   │ ╞═════╪═════╡ │     │       │        │        │
--   │ └─────┴─────┘ │     │       │        │        │
--   │ ┌─────┬─────┐ │ S1  │ Smith │ 20     │ London │
--   │ │ pno │ qty │ │     │       │        │        │
--   │ ╞═════╪═════╡ │     │       │        │        │
--   │ │ P1  │ 300 │ │     │       │        │        │
--   │ │ P2  │ 200 │ │     │       │        │        │
--   ...
--   
-- -- See material about extend, image relations and RVAs in [1] chapter 7 -- for more. -- -- Note the additional plumbing required to employ relvars inside the -- function extend takes; the function imageExtendL has -- been created to provide a more convenient way to express this, -- specializing upon extend and image. extend :: (Ord (HList (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r r'1)), HDeleteLabels (LabelsOf r) r' r'1, HAppendList r r'1, HAllTaggedLV (HAppendListR * r r'1), MonOp a, (~) * (MonOpArg a) (Set (RTuple r'))) => a -> (Record r' -> Record r) -> MonOpRes a (Relation (HAppendListR * r r'1)) -- | Restricts the given relation according to the given predicate. Note -- that this is the well known WHERE operator of both SQL and -- Tutorial D, but since "where" is a reserved keyword in Haskell it is -- named "restrict". -- --
--   >>> rPrint$ p `restrict` (\[pun|weight|] -> weight < 17.5)
--   ┌─────┬───────┬───────┬────────┬────────┐
--   │ pno │ pName │ color │ weight │ city   │
--   ╞═════╪═══════╪═══════╪════════╪════════╡
--   │ P1  │ Nut   │ Red   │ 12 % 1 │ London │
--   ...
--   │ P5  │ Cam   │ Blue  │ 12 % 1 │ Paris  │
--   └─────┴───────┴───────┴────────┴────────┘
--   
restrict :: (MonOp a, (~) * (MonOpArg a) (Set a1)) => a -> (a1 -> Bool) -> MonOpRes a (Set a1) -- | Projects the given relation on the given heading. -- --
--   >>> rPrint$ p `project` (rHdr (color,city))
--   ┌───────┬────────┐
--   │ color │ city   │
--   ╞═══════╪════════╡
--   │ Blue  │ Oslo   │
--   │ Blue  │ Paris  │
--   │ Green │ Paris  │
--   │ Red   │ London │
--   └───────┴────────┘
--   
project :: (Ord (HList a1), HLabelSet [*] (LabelsOf a1), H2ProjectByLabels ls t a1 b, HAllTaggedLV a1, MonOp a, (~) * (MonOpArg a) (Set (RTuple t))) => a -> proxy ls -> MonOpRes a (Relation a1) -- | Projects the given relation on the heading of said given relation -- minus the given heading. -- --
--   >>> rPrint$ p `projectAllBut` (rHdr (city))
--   ┌─────┬───────┬───────┬────────┐
--   │ pno │ pName │ color │ weight │
--   ╞═════╪═══════╪═══════╪════════╡
--   │ P1  │ Nut   │ Red   │ 12 % 1 │
--   │ P2  │ Bolt  │ Green │ 17 % 1 │
--   │ P3  │ Screw │ Blue  │ 17 % 1 │
--   │ P4  │ Screw │ Red   │ 14 % 1 │
--   │ P5  │ Cam   │ Blue  │ 12 % 1 │
--   │ P6  │ Cog   │ Red   │ 19 % 1 │
--   └─────┴───────┴───────┴────────┘
--   
projectAllBut :: (Ord (HList r'), HDeleteLabels ks r r', MonOp a, (~) * (MonOpArg a) (Set (RTuple r))) => a -> proxy ks -> MonOpRes a (Relation r') -- | Groups the given attributes of the given relation into a given new -- relation valued attribute. -- -- As the Tutorial D GROUP operator, not SQL GROUP BY. -- --
--   >>> let pq = (Label :: Label "pq")
--   
--   >>> pt$ group sp (rHdr (pno,qty)) (pq .=.)
--   ┌────────────────────────────────────┬───────────────┐
--   │ pq :: Relation '["pno","qty"]      │ sno :: String │
--   ╞════════════════════════════════════╪═══════════════╡
--   │ ┌───────────────┬────────────────┐ │ S1            │
--   │ │ pno :: String │ qty :: Integer │ │               │
--   │ ╞═══════════════╪════════════════╡ │               │
--   │ │ P1            │ 300            │ │               │
--   ...
--   └────────────────────────────────────┴───────────────┘
--   
-- -- Note that the last argument is a function that tags any value with a -- label; an attribute constructor. This is different from Tutorial D -- GROUP, which just takes the equivalent of a label, but as -- long as an attribute constructor is provided it will function the same -- way. Here is what we get if we aggregate the relation we get as the -- argument to the receiving function with agg, instead of just -- supplying an attribute constructor ("(pq .=.)" above): -- --
--   >>> let qtys = (Label :: Label "qtys")
--   
--   >>> pt$ group sp (rHdr (pno,qty))
--                    ((qtys .=.) . agg qty)
--   ┌───────────────────────────┬───────────────┐
--   │ qtys :: [Integer]         │ sno :: String │
--   ╞═══════════════════════════╪═══════════════╡
--   │ [200]                     │ S3            │
--   │ [200,300,400]             │ S4            │
--   │ [300,200,400,200,100,100] │ S1            │
--   │ [300,400]                 │ S2            │
--   └───────────────────────────┴───────────────┘
--   
-- -- "Get the quantities of items in stock for those suppliers that supply -- anything": -- --
--   >>> pt$ group sp (rHdr (pno,qty)) ((qtys .=.) . sum . agg qty)
--   ┌─────────────────┬───────────────┐
--   │ qtys :: Integer │ sno :: String │
--   ╞═════════════════╪═══════════════╡
--   │ 200             │ S3            │
--   │ 700             │ S2            │
--   │ 900             │ S4            │
--   │ 1300            │ S1            │
--   └─────────────────┴───────────────┘
--   
-- -- Note the difference between this and the example for image. -- These last two examples may be more clearly expressed with -- groupAllBut, since we then specify the attributes that the -- resulting type will have. group :: (Eq (HList l), Ord v, Ord (HList r'), Ord (HList l1), HLabelSet [*] (LabelsOf l), HLabelSet [*] ((:) * (Label k t) (LabelsOf l1)), H2ProjectByLabels (LabelsOf l) r l b, H2ProjectByLabels (LabelsOf r) l1 l b1, HDeleteLabels ks r l1, HDeleteLabels (LabelsOf l1) r r', HAllTaggedLV l1, HAllTaggedLV l, MonOp a, (~) * (MonOpArg a) (Set (RTuple r))) => a -> proxy ks -> (Relation r' -> Tagged k t v) -> MonOpRes a (Relation ((:) * (Tagged k t v) l1)) -- | Groups the given relation on all but the given attributes into a given -- new attribute. -- --
--   >>> pt$ groupAllBut sp (rHdr (sno)) (pq .=.)
--   
-- -- Same result as the first example for group. -- --
--   >>> pt$ groupAllBut sp (rHdr (sno)) ((qtys .=.) . sum . agg qty )
--   
-- -- Same result as the last example for group. groupAllBut :: (Eq (HList l), Ord v, Ord (HList r'), Ord (HList l1), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf l1), HLabelSet [*] ((:) * (Label k t) (LabelsOf l1)), H2ProjectByLabels ls t1 l1 b2, H2ProjectByLabels (LabelsOf l) t1 l b, H2ProjectByLabels (LabelsOf t1) l1 l b1, HDeleteLabels (LabelsOf l1) t1 r', HAllTaggedLV l1, HAllTaggedLV l, MonOp a, (~) * (MonOpArg a) (Set (RTuple t1))) => a -> proxy ls -> (Relation r' -> Tagged k t v) -> MonOpRes a (Relation ((:) * (Tagged k t v) l1)) -- | Ungroups the given relation valued attribute of the given relation. -- --
--   >>> sp `rEq` ungroup ( group sp (rHdr (pno,qty)) (pq .=.)) (undefined :: Label "pq")
--   True
--   
ungroup :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), HasField k l1 (Record v) (Relation t), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b, H2ProjectByLabels ((:) * (Label k l1) ([] *)) v t3 t1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR * t1 t2), MonOp a, (~) * (MonOpArg a) (Set (RTuple v))) => a -> Label k l1 -> MonOpRes a (Relation (HAppendListR * t1 t2)) -- | Disjoint extension. Extends the given relation with the result of the -- second argument, as extend, but without deleting any that -- exist. dExtend :: (Ord (HList (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r' r)), HDeleteLabels (LabelsOf r) r' r'1, HAppendList r r'1, HAllTaggedLV (HAppendListR * r r'1), HAllTaggedLV (HAppendListR * r' r), MonOp a, (~) * (MonOpArg a) (Set (RTuple r'))) => a -> (Record r' -> Record r) -> MonOpRes a (Relation (HAppendListR * r r'1)) -- | Extends the given relation with the attribute resulting from the -- second argument. If an attribute with the same name exists then it -- will be replaced. This allows for the function of the second argument -- to be simpler than for extend, which must return an r-tuple. -- -- Where c is an expression yielding a single attribute: -- --
--   >>> extend a (\b -> c .*. emptyRecord)
--   
-- -- Is equivalent to: -- --
--   >>> extendA a (\b -> c)
--   
-- -- The following has the same result as the first example for -- extend: -- --
--   >>> let gmwt = (Label::Label "gmwt")
--   
--   >>> rPrint$ extendA p (\[pun|weight|] -> gmwt .=. weight * 454)
--   
-- -- Note that if one wants to alter the values of an existing attribute -- then one has to avoid a name collision. The most convenient option -- will most often be having a constructor function or label constant -- with a different name from the actual label: -- --
--   >>> let _weight a = (Label::Label "weight") .=. a
--   
--   >>> rPrint$ extendA p (\[pun|weight|] -> _weight $ weight + 10)
--   
extendA :: (Ord (HExtendR (Tagged k l e) (r v')), HExtend (Tagged k l e) (r v'), HDeleteAtLabel k r l v v', MonOp a, (~) * (MonOpArg a) (Set (r v))) => a -> (r v -> Tagged k l e) -> MonOpRes a (Set (HExtendR (Tagged k l e) (r v'))) -- | Disjoint extension of a single attribute. Extends the given relation -- with the result of the second argument, as extend, but without -- deleting any that exist. l cannot already have any attribute -- e. dExtendA :: (Ord (HExtendR e l), HExtend e l, MonOp a, (~) * (MonOpArg a) (Set l)) => a -> (l -> e) -> MonOpRes a (Set (HExtendR e l)) -- | Renames one attribute. -- --
--   >>> let sCity = Label :: Label "sCity"
--   
--   >>> rPrint$ s `renameA` (city `as` sCity)
--   ┌────────┬─────┬───────┬────────┐
--   │ sCity  │ sno │ sName │ status │
--   ╞════════╪═════╪═══════╪════════╡
--   │ Athens │ S5  │ Adams │ 30     │
--   │ London │ S1  │ Smith │ 20     │
--   │ London │ S4  │ Clark │ 20     │
--   │ Paris  │ S2  │ Jones │ 10     │
--   │ Paris  │ S3  │ Blake │ 30     │
--   └────────┴─────┴───────┴────────┘
--   
-- -- This only accepts a single pair of labels, the label to rename and the -- new label, in contrast to Tutorial D rename which takes a set of -- from-to pairs. -- -- renameA can, unlike rename, be used by restrict -- and extend: -- --
--   >>> :{
--     do spx <- readRelvar sp
--        rPrint$ sp `restrict` (\( image -> ii ) ->
--                               count ( ii $ renameA (renameA spx (sno `as` sn)) (pno `as` pn) )
--                               > 2)
--   :}
--   ...
--   
renameA :: (Ord (HExtendR (Tagged k1 l1 v1) (r v')), HasField k l (r v) v1, HExtend (Tagged k1 l1 v1) (r v'), HDeleteAtLabel k r l v v', MonOp a, (~) * (MonOpArg a) (Set (r v))) => a -> Tagged k l (Label k1 l1) -> MonOpRes a (Set (HExtendR (Tagged k1 l1 v1) (r v'))) -- | Self-summarization, the special case of summarize where the -- source and target relations is the same. This is closer to SQL GROUP -- BY. -- --
--   >>> pt$ aSummarize sp (rHdr (pno,qty)) (\r -> qty .=. sum ( agg qty r ) .*. emptyRecord)
--   
-- -- Same result as last example for group. aSummarize :: (Eq (HList l), Ord (HList r'2), Ord (HList r'), Ord (HList (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r' r)), HLabelSet [*] (LabelsOf l), H2ProjectByLabels (LabelsOf l) r1 l b, H2ProjectByLabels (LabelsOf r1) r' l b1, HDeleteLabels ks r1 r', HDeleteLabels (LabelsOf r) r' r'1, HDeleteLabels (LabelsOf r') r1 r'2, HAppendList r r'1, HAllTaggedLV l, HAllTaggedLV (HAppendListR * r r'1), HAllTaggedLV (HAppendListR * r' r), MonOp a, (~) * (MonOpArg a) (Set (RTuple r1))) => a -> proxy ks -> (Relation r'2 -> Record r) -> MonOpRes a (Relation (HAppendListR * r r'1)) -- | Extends the first given relation with an attribute resulting from -- imaging each tuple of said relation against the second given relation. -- The following command gives a result that includes the information -- given by SQL RIGHT OUTER JOIN: -- --
--   >>> rPrint$ imageExtendL s sp pq
--   ┌───────────────┬─────┬───────┬────────┬────────┐
--   │ pq            │ sno │ sName │ status │ city   │
--   ╞═══════════════╪═════╪═══════╪════════╪════════╡
--   │ ┌─────┬─────┐ │ S5  │ Adams │ 30     │ Athens │
--   │ │ pno │ qty │ │     │       │        │        │
--   │ ╞═════╪═════╡ │     │       │        │        │
--   │ └─────┴─────┘ │     │       │        │        │
--   │ ┌─────┬─────┐ │ S1  │ Smith │ 20     │ London │
--   │ │ pno │ qty │ │     │       │        │        │
--   │ ╞═════╪═════╡ │     │       │        │        │
--   │ │ P1  │ 300 │ │     │       │        │        │
--   │ │ P2  │ 200 │ │     │       │        │        │
--   ...
--   
-- -- See also extend, which this function specializes, and -- image, which it uses to perform this specialization. imageExtendL :: (Eq (HList l), Ord (HList l1), Ord (HList r'), HLabelSet (LabelsOf l), HLabelSet (Label t : LabelsOf l1), HDeleteLabels (LabelsOf l1) r r', H2ProjectByLabels (LabelsOf l) r l b1, H2ProjectByLabels (LabelsOf r) l1 l b2, HAllTaggedLV l1, HAllTaggedLV l, DyaOp a b, DyaOpLeft a ~ Set (Record l1), DyaOpRight b ~ Relation r) => a -> b -> Label t -> DyaOpRes a b (Set (Record (Tagged t (Relation r') : l1))) -- | The image of a relation corresponding to an r-tuple. -- -- An application of the first argument only, an r-tuple, to this -- function yields what is known as the !! operator in Tutorial -- D. -- --
--   >>> rPrint$ rTuple (sno .=. "S2", pno .=. "P1")
--   ┌─────┬─────┐
--   │ sno │ pno │
--   ├─────┼─────┤
--   │ S2  │ P1  │
--   └─────┴─────┘
--   
--   >>> rPrint$ rTuple (sno .=. "S2", pName .=. "Nut")
--   ┌─────┬───────┐
--   │ sno │ pName │
--   ├─────┼───────┤
--   │ S2  │ Nut   │
--   └─────┴───────┘
--   
--   >>> rPrint$ rTuple (sno .=. "S2", pno .=. "P1") `image` sp
--   ┌─────┐
--   │ qty │
--   ╞═════╡
--   │ 300 │
--   └─────┘
--   
--   >>> rPrint$ rTuple (sno .=. "S2", pName .=. "Nut") `image` sp
--   ┌─────┬─────┐
--   │ pno │ qty │
--   ╞═════╪═════╡
--   │ P1  │ 300 │
--   │ P2  │ 400 │
--   └─────┴─────┘
--   
-- -- Image relations give rise to summarization. Here is a form of the -- query, "get the quantities of items in stock for all suppliers": -- --
--   >>> :{
--   do sp' <- readRelvar sp
--      rPrint$ s `project` (rHdr (sno))
--                `extendA` (\ (image -> ii) ->
--                             (Label::Label "qtySum") .=. ( sum $ agg qty $ ii sp' ) )
--   :}
--   ┌────────┬─────┐
--   │ qtySum │ sno │
--   ╞════════╪═════╡
--   │ 0      │ S5  │
--   │ 200    │ S3  │
--   │ 700    │ S2  │
--   │ 900    │ S4  │
--   │ 1300   │ S1  │
--   └────────┴─────┘
--   
-- -- Note how view patterns are used to build the ii operator, -- equivalent of Tutorial D's !! operator. An equivalent form of -- the lambda would be: -- --
--   (\t -> (Label::Label "qtySum") .=. ( sum $ agg qty $ t `image` sp' ))
--   
-- -- See group for a similar example. image :: (Eq (HList l), Ord (HList r'), HLabelSet [*] (LabelsOf l), H2ProjectByLabels (LabelsOf l) r l b, H2ProjectByLabels (LabelsOf r) l1 l b1, HDeleteLabels (LabelsOf l1) r r', HAllTaggedLV l, MonOp a, (~) * (MonOpArg a) (Set (RTuple r))) => Record l1 -> a -> MonOpRes a (Relation r') -- | Gives whether a given r-tuple is member of a given relation. -- --
--   >>> member (rTuple(sno .=. "S3", qty .=. 200, pno .=. "P2")) sp
--   True
--   
member :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => Record r -> a -> MonOpRes a Bool -- | Gives whether a given r-tuple is not a member of a given relation. -- --
--   >>> notMember (rTuple(sno .=. "S3", qty .=. 200, pno .=. "P2")) sp
--   False
--   
notMember :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => Record r -> a -> MonOpRes a Bool -- | Right-fold of an attribute of a relation (although a "right" fold -- doesn't make sense in the context of the relational model). Note that -- the value of the third argument is not used and may be "undefined". -- --
--   >>> rafoldr (+) 0 qty sp
--   3100
--   
--   >>> rafoldr (*) 1 qty sp
--   27648000000000000000000000000
--   
rafoldr :: (Foldable t, HasField k l a1 b1, MonOp a, (~) * (MonOpArg a) (t a1)) => (b1 -> res -> res) -> res -> Label k l -> a -> MonOpRes a res -- | Right-fold of the attribute of an unary relation. -- --
--   >>> rafoldrU (+) 0 $ sp `project` (rHdr (qty))
--   1000
--   
--   >>> rafoldrU (*) 1 $ sp `project` (rHdr (qty))
--   2400000000
--   
rafoldrU :: (Foldable t, MonOp a, (~) * (MonOpArg a) (t (Record ((:) * (Tagged k t1 b1) ([] *))))) => (b1 -> res -> res) -> res -> a -> MonOpRes a res -- | Attribute value aggregation, a specialization of rafoldr that -- aggregates the values of a single attribute into a list of the values -- the attribute type wraps. -- -- Note that the value of the first argument is not used and may be -- "undefined". -- --
--   >>> :{
--    do sp' <- readRelvar sp
--       putStrLn $ show $ sum $ agg qty sp'
--   :}
--   3100
--   
agg :: (Foldable t, HasField l a1 a2, MonOp a, MonOpArg a ~ t a1) => Label l -> a -> MonOpRes a [a2] -- | Aggregation of the single attribute of an unary relation. A -- specialization of agg, and thus in turn of rafoldr, that -- aggregates the single attribute of a unary relation, without requiring -- the name of that attribute. -- --
--   >>> :{
--    do sp' <- readRelvar sp
--       putStrLn $ show $ sum $ aggU $ sp' `project` (rHdr (qty))
--    :}
--   1000
--   
aggU :: (Foldable t, MonOp a, MonOpArg a ~ t (Record '[Tagged t1 a1])) => a -> MonOpRes a [a1] -- | Gives the cardinality of the argument. -- --
--   >>> count sp
--   12
--   
count :: (MonOp a, MonOpArg a ~ Set a1) => a -> MonOpRes a Int -- | Gives whether the given argument is empty or not. -- --
--   >>> isEmpty sp
--   False
--   
isEmpty :: (MonOp a, MonOpArg a ~ Set a1) => a -> MonOpRes a Bool -- | Aggregates an attribute and applies a function to the result of that. -- A specialization of rafoldr. -- -- Note that the value of the first argument is not used and may be -- "undefined". -- --
--   >>> rAgg qty sp sum
--   3100
--   
rAgg :: (Foldable t, HasField l a1 a2, MonOp a, MonOpArg a ~ t a1) => Label l -> a -> ([a2] -> res) -> MonOpRes a res -- | Aggregates the attribute of an unary relation and applies a function -- to the result of that. A specialization of rafoldrU. -- --
--   >>> rAggU (sp `project` (rHdr (qty))) sum
--   1000
--   
rAggU :: (Foldable t, MonOp a, (~) * (MonOpArg a) (t (Record ((:) * (Tagged k t1 a1) ([] *))))) => a -> ([a1] -> res) -> MonOpRes a res -- | The class of relational dyadic operators class DyaOp a b where type family DyaOpRes a b res :: * type family DyaOpLeft a :: * type family DyaOpRight b :: * DyaOpRes a b res = IO res -- | Binary relational function application. -- --
--   >>> let newSups = ( relation [rTuple (sno .=. "S6", sName .=. "Nena", city .=. "Berlin", status .=. 40)] )
--   
--   >>> dyaOp (/=) s newSups
--   True
--   
dyaOp :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r, DyaOp a b, DyaOpRight b ~ Relation r) => (DyaOpLeft a -> Relation l -> res) -> a -> b -> DyaOpRes a b res -- | The natural join of the two given relations. -- --
--   >>> rPrint$ sp `naturalJoin` s
--   ┌─────┬─────┬─────┬───────┬────────┬────────┐
--   │ sno │ pno │ qty │ sName │ status │ city   │
--   ╞═════╪═════╪═════╪═══════╪════════╪════════╡
--   │ S1  │ P1  │ 300 │ Smith │ 20     │ London │
--   ...
--   │ S4  │ P5  │ 400 │ Clark │ 20     │ London │
--   └─────┴─────┴─────┴───────┴────────┴────────┘
--   
naturalJoin :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR * t1 t2), DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | Alias of naturalJoin. nJoin :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR * t1 t2), DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | The cartesian product of two relations. A specialized natural join; -- the natural join between two relations with disjoint headings. -- --
--   >>> rPrint$ ( sp `projectAllBut` (rHdr (city)) ) `times` ( s `projectAllBut` (rHdr (city)) )
--   ...
--       No instance for (Fail (DuplicatedLabel (Label "sno")))
--         arising from a use of ‘times’
--   
-- --
--   >>> rPrint$ ( sp `projectAllBut` (rHdr (sno)) ) `times` ( s `projectAllBut` (rHdr (sno)) )
--   ┌─────┬─────┬───────┬────────┬────────┐
--   │ pno │ qty │ sName │ status │ city   │
--   ╞═════╪═════╪═══════╪════════╪════════╡
--   │ P1  │ 300 │ Adams │ 30     │ Athens │
--   │ P1  │ 300 │ Blake │ 30     │ Paris  │
--   ...
--   │ P6  │ 100 │ Jones │ 10     │ Paris  │
--   │ P6  │ 100 │ Smith │ 20     │ London │
--   └─────┴─────┴───────┴────────┴────────┘
--   
times :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf (HAppendListR * t r)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV r, HAllTaggedLV l, HAllTaggedLV (HAppendListR * t1 t2), HAllTaggedLV (HAppendListR * t r), DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | The semi-join of the first given relation against the second given -- relation. -- --
--   >>> rPrint$ s `matching` sp
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   │ S1  │ Smith │ 20     │ London │
--   │ S2  │ Jones │ 10     │ Paris  │
--   │ S3  │ Blake │ 30     │ Paris  │
--   │ S4  │ Clark │ 20     │ London │
--   └─────┴───────┴────────┴────────┘
--   
matching :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | Alias of matching. semiJoin :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | The semi-difference of the first given relation against the second -- given relation. Aka. antijoin. -- --
--   >>> rPrint$ s `notMatching` sp
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   │ S5  │ Adams │ 30     │ Athens │
--   └─────┴───────┴────────┴────────┘
--   
notMatching :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | Alias of notMatching. semiDiff :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | The union of two relations. -- --
--   >>> let newSups = ( relation [rTuple (sno .=. "S6", sName .=. "Nena", city .=. "Berlin", status .=. 40)] )
--   
--   >>> rPrint$ s `union` newSups
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   │ S1  │ Smith │ 20     │ London │
--   │ S2  │ Jones │ 10     │ Paris  │
--   │ S3  │ Blake │ 30     │ Paris  │
--   │ S4  │ Clark │ 20     │ London │
--   │ S5  │ Adams │ 30     │ Athens │
--   │ S6  │ Nena  │ 40     │ Berlin │
--   └─────┴───────┴────────┴────────┘
--   
union :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | The disjoint union between the relations. This is a union of disjoint -- relations, where a runtime error is raised if the arguments are not -- disjoint. -- --
--   >>> :{
--     rPrint$ ( p' `project` (rHdr (city)) )
--             `dUnion`
--             ( s' `project` (rHdr (city)) )
--   :}
--   ┌─*** Exception: Arguments to dUnion are not disjoint, intersection:
--   ┌────────┐
--   │ city   │
--   ╞════════╡
--   │ London │
--   │ Paris  │
--   └────────┘
--   
dUnion :: (Ord (HList a1), Typeable [*] a1, HLabelSet [*] (LabelsOf a1), RecordValues a1, HRearrange3 (LabelsOf a1) r a1, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a1) [[String]], SameLength' * * a1 r, SameLength' * * r a1, SameLength' * * r (LabelsOf a1), SameLength' * * (LabelsOf a1) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple a1))) => a -> b -> DyaOpRes a b (Relation a1) -- | The intersection of two relations. -- -- Note how the name is different from Data.Set, where it is named -- "intersection". This is due to it being referred to as "intersect" in -- material describing the relational model; specifically named -- "INTERSECT" in Tutorial D. -- --
--   >>> let sX = ( relation [rTuple (sno .=. "S2", sName .=. "Jones", city .=. "Paris", status .=. 10), rTuple (sno .=. "S6", sName .=. "Nena", city .=. "Berlin", status .=. 40)] )
--   
--   >>> rPrint$ s `intersect` sX
--   ┌─────┬───────┬────────┬───────┐
--   │ sno │ sName │ status │ city  │
--   ╞═════╪═══════╪════════╪═══════╡
--   │ S2  │ Jones │ 10     │ Paris │
--   └─────┴───────┴────────┴───────┘
--   
-- -- Notably, for any given relation values r1 and r2 that are of the same -- type it holds that: -- --
--   r1 `intersect` r2 == r1 `naturalJoin` r2
--   
-- -- Within relational theory the natural join generalizes as such both -- intersection and cartesian product. intersect :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | The difference of two relations. -- -- The "minus" term is used in material describing relational theory; -- specifically Tutorial D names the operator "MINUS". -- --
--   >>> rPrint$ s `minus` sX
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   │ S1  │ Smith │ 20     │ London │
--   │ S3  │ Blake │ 30     │ Paris  │
--   │ S4  │ Clark │ 20     │ London │
--   │ S5  │ Adams │ 30     │ Athens │
--   └─────┴───────┴────────┴────────┘
--   
minus :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | Exclusive union, aka. symmetric difference -- --
--   >>> rPrint$ s `xUnion` sX
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   │ S1  │ Smith │ 20     │ London │
--   │ S3  │ Blake │ 30     │ Paris  │
--   │ S4  │ Clark │ 20     │ London │
--   │ S5  │ Adams │ 30     │ Athens │
--   │ S6  │ Nena  │ 40     │ Berlin │
--   └─────┴───────┴────────┴────────┘
--   
xUnion :: (Ord (HList r1), HLabelSet [*] (LabelsOf r1), HRearrange3 (LabelsOf r1) r1 r1, HRearrange3 (LabelsOf r1) r r1, SameLength' * * r1 r1, SameLength' * * r1 r, SameLength' * * r1 (LabelsOf r1), SameLength' * * r r1, SameLength' * * r (LabelsOf r1), SameLength' * * (LabelsOf r1) r1, SameLength' * * (LabelsOf r1) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple r1))) => a -> b -> DyaOpRes a b (Relation r1) -- | Tests whether the second argument is a proper subset of the first. -- --
--   >>> let spX = relation [rTuple (sno .=. "S1", pno .=. "P4", qty .=. 200), rTuple (sno .=. "S2", pno .=. "P2", qty .=. 400)]
--   
--   >>> spX `isProperSubsetOf` sp
--   True
--   
isProperSubsetOf :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b Bool -- | Tests whether the second argument is a subset of the first. -- --
--   >>> spX `isSubsetOf` sp
--   True
--   
isSubsetOf :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b Bool -- | Relational equality. -- --
--   >>> sp `rEq` (relation [rTuple(sno .=. "S2", qty .=. 400, pno .=. "P2")])
--   False
--   
rEq :: (Ord (HList l), HRearrange3 (LabelsOf l) r l, HLabelSet (LabelsOf l), SameLength' r l, SameLength' r (LabelsOf l), SameLength' l r, SameLength' (LabelsOf l) r, DyaOp a b, DyaOpLeft a ~ Relation l, DyaOpRight b ~ Relation r) => a -> b -> DyaOpRes a b Bool -- | The summarization of the relations by the given function. -- --
--   >>> let pct = Label :: Label "pct"
--   
--   >>> rPrint$ summarize sp (s `project` (rHdr (sno))) (rHdr (pno)) (\r -> pct .=. count r .*. emptyRecord)
--   ┌─────┬─────┐
--   │ pct │ sno │
--   ╞═════╪═════╡
--   │ 0   │ S5  │
--   │ 1   │ S3  │
--   │ 2   │ S2  │
--   │ 3   │ S4  │
--   │ 6   │ S1  │
--   └─────┴─────┘
--   
-- --
--   >>> rPrint$ summarize sp (s `project` (rHdr (sno))) (rHdr (qty)) (\r -> qty .=. sum ( agg qty r ) .*. emptyRecord)
--   ┌──────┬─────┐
--   │ qty  │ sno │
--   ╞══════╪═════╡
--   │ 0    │ S5  │
--   │ 200  │ S3  │
--   │ 700  │ S2  │
--   │ 900  │ S4  │
--   │ 1300 │ S1  │
--   └──────┴─────┘
--   
summarize :: (Eq (HList l), Ord (HList r'2), Ord (HList r'), Ord (HList (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r r'1)), HLabelSet [*] (LabelsOf (HAppendListR * r' r)), HLabelSet [*] (LabelsOf l), H2ProjectByLabels (LabelsOf l) r1 l b1, H2ProjectByLabels (LabelsOf r1) r' l b2, HDeleteLabels ks r2 r', HDeleteLabels (LabelsOf r) r' r'1, HDeleteLabels (LabelsOf r') r1 r'2, HAppendList r r'1, HAllTaggedLV l, HAllTaggedLV (HAppendListR * r r'1), HAllTaggedLV (HAppendListR * r' r), DyaOp a b, (~) * (DyaOpLeft a) (Set (RTuple r1)), (~) * (DyaOpRight b) (Set (RTuple r2))) => a -> b -> proxy ks -> (Relation r'2 -> Record r) -> DyaOpRes a b (Relation (HAppendListR * r r'1)) -- | The natural join between two relations with intersecting headings. A -- specialized natural join. -- -- A join upon relations r1, r2 where the intersection of the heading of -- r1 and of r2 is not empty; the headings are not disjoint. This is a -- complement of times within natural join; all values that -- naturalJoin accepts as operands and times does not -- are accepted by interJoin, and vice-versa. The name is what I -- quickly settled on, suggestions for a better one would be welcome. -- (Attribute-Intersecting Natural Join is another candidate.) -- -- This function doesn't have a specific identity value, although it -- holds that r `interJoin` r = r -- --
--   >>> rPrint$ ( sp `projectAllBut` (rHdr (sno)) ) `interJoin` ( s `projectAllBut` (rHdr (sno)) )
--   ...
--       Overlapping instances for NotEmpty '[]
--         arising from a use of ‘interJoin’
--   
-- --
--   >>> rPrint$ sp `interJoin` s
--   ┌─────┬─────┬─────┬───────┬────────┬────────┐
--   │ sno │ pno │ qty │ sName │ status │ city   │
--   ╞═════╪═════╪═════╪═══════╪════════╪════════╡
--   │ S1  │ P1  │ 300 │ Smith │ 20     │ London │
--   │ S1  │ P2  │ 200 │ Smith │ 20     │ London │
--   ...
--   │ S4  │ P4  │ 300 │ Clark │ 20     │ London │
--   │ S4  │ P5  │ 400 │ Clark │ 20     │ London │
--   └─────┴─────┴─────┴───────┴────────┴────────┘
--   
interJoin :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t) t1 r b1, H2ProjectByLabels (LabelsOf t1) t l t2, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, HTIntersect (LabelsOf r) (LabelsOf t) i, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV r, HAllTaggedLV l, HAllTaggedLV (HAppendListR * t1 t2), NotEmpty i, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | Alias of interJoin iJoin :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t) t1 r b1, H2ProjectByLabels (LabelsOf t1) t l t2, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, HTIntersect (LabelsOf r) (LabelsOf t) i, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR * t1 t2), NotEmpty i, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | The class of relational assignment class RelAssign a where type family RelAssignArg a :: * -- | Relational IO function application. relAssign :: RelAssign a => (RelAssignArg a -> IO ()) -> a -> IO () -- | Writes a relation value to a relvar file, replacing the existing -- value. -- --
--   >>> assign s s'
--   Value assigned to SuppliersPartsDB/S.rv
--   
assign :: (Ord (HList a1), Show (HList (RecordValuesR a1)), HLabelSet [*] (LabelsOf a1), RecordValues a1, HRearrange3 (LabelsOf a1) r a1, SameLength' * * a1 r, SameLength' * * r a1, SameLength' * * r (LabelsOf a1), SameLength' * * (LabelsOf a1) r, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple r))) => Relvar a1 -> a -> IO () -- | Inserts a relation into a relvar. This differs from SQLs INSERT; the -- relvar is updated to the union of the relvar and the relation value -- given as arguments. -- --
--   >>> let newSups = relation [rTuple (sno .=. "S6", sName .=. "Nena", city .=. "Berlin", status .=. 40)]
--   
--   >>> insert s newSups
--   Inserted 1 of 1 tuples into SuppliersPartsDB/S.rv
--   
--   >>> insert s newSups
--   Inserted 0 of 1 tuples into SuppliersPartsDB/S.rv
--   
--   >>> rPrint$ s
--   ┌─────┬───────┬────────┬────────┐
--   │ sno │ sName │ status │ city   │
--   ╞═════╪═══════╪════════╪════════╡
--   ...
--   │ S6  │ Nena  │ 40     │ Berlin │
--   └─────┴───────┴────────┴────────┘
--   
insert :: (Ord (HList a1), Read (HList (RecordValuesR a1)), Show (HList (RecordValuesR a1)), HLabelSet [*] (LabelsOf a1), RecordValues a1, HRearrange3 (LabelsOf a1) r a1, HMapAux HList TaggedFn (RecordValuesR a1) a1, SameLength' * * a1 r, SameLength' * * r a1, SameLength' * * r (LabelsOf a1), SameLength' * * (LabelsOf a1) r, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple r))) => Relvar a1 -> a -> IO () -- | Disjoint insert. Closer to SQL INSERT, except that this will never -- insert a duplicate tuple. -- --
--   >>> dInsert sp $ relation [rTuple (sno .=. "S6", pno .=. "P7", qty .=. 99)]
--   Inserted 1 tuples into SuppliersPartsDB/SP.rv
--   
--   >>> dInsert sp $ relation [rTuple (sno .=. "S6", pno .=. "P7", qty .=. 99), rTuple (sno .=. "S4", pno .=. "P4", qty .=. 300), rTuple (sno .=. "S7", pno .=. "P8", qty .=. 200)]
--   *** Exception: Unique constraint violation, tuples already present in SuppliersPartsDB/SP.rv:
--   ┌─────┬─────┬─────┐
--   │ sno │ pno │ qty │
--   ╞═════╪═════╪═════╡
--   │ S4  │ P4  │ 300 │
--   │ S6  │ P7  │ 99  │
--   └─────┴─────┴─────┘
--   
dInsert :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR r)), Typeable [*] t, HLabelSet [*] (LabelsOf t), RecordValues t, RecordValues r, HRearrange3 (LabelsOf t) r t, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR t) [[String]], HMapAux HList TaggedFn (RecordValuesR t) t, SameLength' * * t r, SameLength' * * r t, SameLength' * * r (LabelsOf t), SameLength' * * (LabelsOf t) r, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple r))) => Relvar t -> a -> IO () -- | Deletes a specified subset of a relvar. Note that this is not SQL -- DELETE, but instead a generalization thereof. -- --
--   >>> delete s newSups
--   Deleted 1 tuples from SuppliersPartsDB/S.rv
--   
delete :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), RecordValues t, HMapAux HList TaggedFn (RecordValuesR t) t, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple t))) => Relvar t -> a -> IO () -- | Performs an inclusive delete against a relvar. Also not SQL DELETE. -- This will fail if the second argument is not a subset of the relation -- variable. -- --
--   >>> iDelete sp $ relation [rTuple (sno .=. "S6", pno .=. "P7", qty .=. 99), rTuple (sno .=. "S4", pno .=. "P4", qty .=. 300), rTuple (sno .=. "S7", pno .=. "P8", qty .=. 200)]
--   *** Exception: Tuples not found in relvar SuppliersPartsDB/SP.rv:
--   ┌─────┬─────┬─────┐
--   │ sno │ pno │ qty │
--   ╞═════╪═════╪═════╡
--   │ S7  │ P8  │ 200 │
--   └─────┴─────┴─────┘
--   
iDelete :: (Ord (HList t), Ord (HList a1), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), Typeable [*] a1, HLabelSet [*] (LabelsOf t), HLabelSet [*] (LabelsOf a1), RecordValues t, RecordValues a1, HRearrange3 (LabelsOf t) a1 t, HRearrange3 (LabelsOf a1) t a1, HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a1) [[String]], HMapAux HList TaggedFn (RecordValuesR t) t, SameLength' * * t a1, SameLength' * * t (LabelsOf a1), SameLength' * * a1 t, SameLength' * * a1 (LabelsOf t), SameLength' * * (LabelsOf t) a1, SameLength' * * (LabelsOf a1) t, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple a1))) => Relvar t -> a -> IO () -- | Delete by predicate, as SQL DELETE. -- --
--   >>> let newProd = relation [rTuple (pno .=. "P7", pName .=. "Baloon", color .=. "Red", weight .=. (-5 :: Rational), city .=. "Berlin")]
--   
--   >>> insert p newProd
--   Inserted 1 of 1 tuples into SuppliersPartsDB/P.rv
--   
--   >>> deleteP p (\ [pun|pno|] -> pno == "P7" )
--   Deleted 1 tuples from SuppliersPartsDB/P.rv
--   
deleteP :: (Ord (HList t), Read (HList (RecordValuesR t)), Show (HList (RecordValuesR t)), RecordValues t, HMapAux HList TaggedFn (RecordValuesR t) t) => Relvar t -> (RTuple t -> Bool) -> IO () -- | Updates tuples of a relvar that match the given predicate. As SQL -- UPDATE. -- --
--   >>> update sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> _qty ( qty - 25 ) .*. emptyRecord)
--   Updated 5 of 12 tuples in SuppliersPartsDB/SP.rv
--   *SuppliersPartsExample> rPrint$ sp
--   ┌─────┬─────┬─────┐
--   │ sno │ pno │ qty │
--   ╞═════╪═════╪═════╡
--   │ S1  │ P1  │ 300 │
--   │ S1  │ P2  │ 175 │
--   │ S1  │ P3  │ 375 │
--   │ S1  │ P4  │ 200 │
--   ...
--   
-- -- Note how the cardinality of the relvar will be equal or lower after an -- update: -- --
--   >>> assign sp sp'
--   Value assigned to SuppliersPartsDB/SP.rv
--   
--   >>> count sp
--   12
--   
--   >>> update sp (\[pun|pno|] -> pno == "P1" || pno == "P2" || pno == "P3") (\_ -> _pno "P1" .*. _qty 50 .*. emptyRecord)
--   Updated 7 of 12 tuples in SuppliersPartsDB/SP.rv
--   
--   >>> count sp
--   9
--   
update :: (Ord (HList a), Read (HList (RecordValuesR a)), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) (HAppendListR r r'2) a, HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)), HDeleteLabels (LabelsOf r) a r'2, HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2, SameLength' a (HAppendListR r r'2), SameLength' (LabelsOf a) (HAppendListR r r'2), SameLength' (HAppendListR r r'2) a, SameLength' (HAppendListR r r'2) (LabelsOf a), HAllTaggedLV (HAppendListR r r'2)) => Relvar a -> (Record a -> Bool) -> (Record a -> Record r) -> IO () -- | Updates tuples of a relvar that match the given predicate. -- -- In SQL and Tutorial D both the predicate of UPDATE is an -- optional clause, but optional clauses isn't idiomatic Haskell, hence -- this separate updateAll function. -- --
--   >>> updateAll sp (\ [pun|qty pno|] -> _qty ( qty - 25 ) .*. _pno ( pno ++ "X" ) .*. emptyRecord)
--   Updated 12 tuples in SuppliersPartsDB/SP.rv
--   *SuppliersPartsExample> pt sp
--   ┌───────────────┬───────────────┬────────────────┐
--   │ sno :: String │ pno :: String │ qty :: Integer │
--   ╞═══════════════╪═══════════════╪════════════════╡
--   │ S1            │ P1X           │ 275            │
--   ...
--   
updateAll :: (Ord (HList a), Read (HList (RecordValuesR a)), Show (HList (RecordValuesR a)), RecordValues a, HRearrange3 (LabelsOf a) (HAppendListR r r'2) a, HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)), HDeleteLabels (LabelsOf r) a r'2, HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2, SameLength' a (HAppendListR r r'2), SameLength' (LabelsOf a) (HAppendListR r r'2), SameLength' (HAppendListR r r'2) a, SameLength' (HAppendListR r r'2) (LabelsOf a), HAllTaggedLV (HAppendListR r r'2)) => Relvar a -> (Record a -> Record r) -> IO () -- | Updates all tuples of a relvar. The second argument is a function that -- results in an attribute, making for a simpler function than for -- update. -- --
--   >>> updateA sp (\ [pun|pno|] -> pno == "P2" || pno == "P3" ) (\ [pun|qty|] -> _qty $ qty - 25)
--   Updated 5 of 12 tuples in SuppliersPartsDB/SP.rv
--   
updateA :: (Ord (HList r), Read (HList (RecordValuesR r)), Show (HList (RecordValuesR r)), HUpdateAtLabel2 k l v r r, RecordValues r, HasField k l (Record r) v, HMapAux HList TaggedFn (RecordValuesR r) r, SameLength' * * r r) => Relvar r -> (Record r -> Bool) -> (Record r -> Tagged k l v) -> IO () -- | Updates all tuples of a relvar. The second argument is a function that -- results in an attribute, making for a simpler function than for -- updateAll. -- --
--   >>> updateAllA sp (\ [pun|qty|] -> _qty $ qty - 50)
--   Updated 12 tuples in SuppliersPartsDB/SP.rv
--   
--   >>> rPrint$ sp
--   ┌───────────────┬───────────────┬────────────────┐
--   │ sno :: String │ pno :: String │ qty :: Integer │
--   ╞═══════════════╪═══════════════╪════════════════╡
--   │ S1            │ P1            │ 250            │
--   ...
--   
updateAllA :: (Ord (HList r), Read (HList (RecordValuesR r)), Show (HList (RecordValuesR r)), HUpdateAtLabel2 k l v r r, RecordValues r, HasField k l (Record r) v, HMapAux HList TaggedFn (RecordValuesR r) r, SameLength' * * r r) => Relvar r -> (Record r -> Tagged k l v) -> IO () -- | Failure class restricting a type-level operation to a non-empty -- result. class NotEmpty (l :: [*]) instance Database.HaskRel.HFWTabulation.HFWPresent (Database.HaskRel.Relational.Definition.Relation r) => Database.HaskRel.HFWTabulation.HFWPresent (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation r)) instance Database.HaskRel.Relational.Expression.MonOp (Database.HaskRel.Relational.Definition.Relation a) instance Database.HaskRel.Relational.Expression.MonOp (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.MonOp (Database.HaskRel.Relational.Variable.Relvar b) instance Database.HaskRel.Relational.Expression.MonOp' (Database.HaskRel.Relational.Definition.Relation a) instance Database.HaskRel.Relational.Expression.MonOp' (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.MonOp' (Database.HaskRel.Relational.Variable.Relvar b) instance Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Definition.Relation a) (Database.HaskRel.Relational.Definition.Relation b) instance Database.HaskRel.Relational.Expression.DyaOp (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) (Database.HaskRel.Relational.Definition.Relation b) instance Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Definition.Relation a) (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation b)) instance Database.HaskRel.Relational.Expression.DyaOp (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation b)) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Definition.Relation a) (Database.HaskRel.Relational.Variable.Relvar b) instance (GHC.Classes.Ord (Data.HList.HList.HList a), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR a)), Data.HList.Record.RecordValues a, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR a) a) => Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Variable.Relvar a) (Database.HaskRel.Relational.Definition.Relation b) instance (GHC.Classes.Ord (Data.HList.HList.HList a), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR a)), Data.HList.Record.RecordValues a, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR a) a) => Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Variable.Relvar a) (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation b)) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.DyaOp (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) (Database.HaskRel.Relational.Variable.Relvar b) instance (GHC.Classes.Ord (Data.HList.HList.HList a), GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR a)), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues a, Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR a) a, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.DyaOp (Database.HaskRel.Relational.Variable.Relvar a) (Database.HaskRel.Relational.Variable.Relvar b) instance Database.HaskRel.Relational.Expression.RelAssign (Database.HaskRel.Relational.Definition.Relation a) instance Database.HaskRel.Relational.Expression.RelAssign (GHC.Types.IO (Database.HaskRel.Relational.Definition.Relation a)) instance (GHC.Classes.Ord (Data.HList.HList.HList b), GHC.Read.Read (Data.HList.HList.HList (Data.HList.Record.RecordValuesR b)), Data.HList.Record.RecordValues b, Data.HList.HList.HMapAux Data.HList.HList.HList Data.HList.Record.TaggedFn (Data.HList.Record.RecordValuesR b) b) => Database.HaskRel.Relational.Expression.RelAssign (Database.HaskRel.Relational.Variable.Relvar b) -- | Functions pertaining to relational theory or set theory named with -- non-ASCII unicode characters, primarily infix operators. Each of these -- is a synonym for an alphabetically named prefix function. -- -- See also: -- http://hackage.haskell.org/package/base-unicode-symbols -- -- TODO: Fix operator precedence, right now one may need to apply more -- parenthesis than should be necessary. module Database.HaskRel.Relational.Unicode -- | Natural join. -- --
--   >>> rPrint$ sp ⋈ s
--   ...
--   
-- -- As naturalJoin. (⋈) :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV l, HAllTaggedLV r, HAllTaggedLV (HAppendListR * t1 t2), DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | Semijoin. -- --
--   >>> rPrint$ s ⋉ sp
--   ...
--   
-- -- As matching. (⋉) :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | Left semijoin. As (flip matching). (⋊) :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => b -> a -> DyaOpRes a b (Relation t) -- | Semidifference. -- --
--   >>> rPrint$ s ◅ sp
--   ...
--   
-- -- As notMatching. (◅) :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => a -> b -> DyaOpRes a b (Relation t) -- | Left semidifference. As (flip notMatching). (▻) :: (Eq (HList l), Ord (HList t), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf r), H2ProjectByLabels (LabelsOf t) l1 l b1, H2ProjectByLabels (LabelsOf l1) t r b2, HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, HAllTaggedLV l, HAllTaggedLV r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple l1)), (~) * (DyaOpLeft a) (Set (RTuple t))) => b -> a -> DyaOpRes a b (Relation t) -- | Times. The special case of natural join where the headings of the -- relations are disjoint. -- --
--   >>> rPrint$ ( sp `projectAllBut` (rHdr (sno)) ) × ( s `projectAllBut` (rHdr (sno)) )
--   ...
--   
-- -- As times. (×) :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf (HAppendListR * t r)), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t1) t l t2, H2ProjectByLabels (LabelsOf t) t1 r b1, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV r, HAllTaggedLV l, HAllTaggedLV (HAppendListR * t1 t2), HAllTaggedLV (HAppendListR * t r), DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | Restriction. -- -- Note that the symbol used here is the divisor symbol, which looks the -- same but is distinct from the vertical bar, or pipe. However, since -- the vertical bar is used in Haskell for different purposes and is for -- that reason not a valid infix operator symbol, this is used instead. -- --
--   >>> rPrint$ p ∣ (\[pun|weight|] -> weight < 17.5)
--   ...
--   
-- -- As restrict. (∣) :: (MonOp a, (~) * (MonOpArg a) (Set a1)) => a -> (a1 -> Bool) -> MonOpRes a (Set a1) -- | Union. -- --
--   >>> rPrint$ s ∪ ( relation [rTuple (sno .=. "S6", sName .=. "Nena", status .=. 40, city .=. "Berlin")] )
--   ...
--   
-- -- As union. (∪) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | Intersection. -- --
--   >>> let sX = ( relation [rTuple (sno .=. "S2", sName .=. "Jones", status .=. 10, city .=. "Paris"), rTuple (sno .=. "S6", sName .=. "Nena", status .=. 40, city .=. "Berlin")] )
--   
--   >>> rPrint$ s ∩ sX
--   ...
--   
-- -- As intersect. (∩) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | Minus. -- -- Note that this is the difference symbol, not a backslash. -- --
--   >>> rPrint$ s ∖ sX
--   ...
--   
-- -- As minus. (∖) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b (Relation l) -- | Projection. -- -- Note that no matter how greek it is π is still a character, and -- Haskell therefore treats it as a prefix operator, which is in line -- with how it is employed. -- --
--   >>> rPrint$ π (rHdr (color,city)) p
--   ...
--   
-- -- As project, but note how the operands are reversed. π :: (Ord (HList a1), HLabelSet [*] (LabelsOf a1), H2ProjectByLabels ls t a1 b, HAllTaggedLV a1, MonOp a, (~) * (MonOpArg a) (Set (RTuple t))) => proxy ls -> a -> MonOpRes a (Relation a1) -- | Is proper subset. -- --
--   >>> let spX = relation [rTuple (sno .=. "S1", pno .=. "P4", qty .=. 200), rTuple (sno .=. "S2", pno .=. "P2", qty .=. 400)]
--   
--   >>> spX ⊂ sp
--   True
--   
-- -- As isProperSubsetOf. (⊂) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b Bool -- | Is subset of. -- --
--   >>> spX ⊆ sp
--   True
--   
-- -- As isSubsetOf. (⊆) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => a -> b -> DyaOpRes a b Bool -- | Left is proper subset of. As (flip isProperSubsetOf). (⊃) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => b -> a -> DyaOpRes a b Bool -- | Left is subset of. As (flip isSubsetOf). (⊇) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * l r, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * (LabelsOf l) r, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple r)), (~) * (DyaOpLeft a) (Set (RTuple l))) => b -> a -> DyaOpRes a b Bool -- | Relational assignment operator. -- -- This uses the COLON EQUALS UTF-8 character (&#8788;), the ASCII -- variant := wouldn't be allowed in Haskell since it starts -- with a colon. -- --
--   >>> s ≔ s'
--   
--   >>> 
--   
-- -- As assign. (≔) :: (Ord (HList a1), Show (HList (RecordValuesR a1)), HLabelSet [*] (LabelsOf a1), RecordValues a1, HRearrange3 (LabelsOf a1) r a1, SameLength' * * a1 r, SameLength' * * r a1, SameLength' * * r (LabelsOf a1), SameLength' * * (LabelsOf a1) r, RelAssign a, (~) * (RelAssignArg a) (Set (RTuple r))) => Relvar a1 -> a -> IO () -- | Attribute intersecting natural join. The special case of natural join -- where the headings of the relations are not disjoint. -- -- Using the "box times" or "squared times" (U+22A0) symbol is my own -- solution. As with the name "(attribute) intersecting natural join" -- suggestions are welcome. -- -- As mentioned in Database.HaskRel.Relational.Algebra, this -- operation doesn't have a single identity value, although it holds that -- for any given relation value r, r ⊠ r = r -- --
--   >>> rPrint$ sp ⊠ s
--   ...
--   
-- -- As interJoin. (⊠) :: (Eq (HList l), Ord (HList (HAppendListR * t1 t2)), HLabelSet [*] (LabelsOf r), HLabelSet [*] (LabelsOf l), HLabelSet [*] (LabelsOf t2), HLabelSet [*] (LabelsOf (HAppendListR * t1 t2)), H2ProjectByLabels (LabelsOf t) t1 r b1, H2ProjectByLabels (LabelsOf t1) t l t2, HRearrange3 (LabelsOf l) r l, HAppendList t1 t2, HTIntersect (LabelsOf r) (LabelsOf t) i, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, HAllTaggedLV t2, HAllTaggedLV r, HAllTaggedLV l, HAllTaggedLV (HAppendListR * t1 t2), NotEmpty i, DyaOp a b, (~) * (DyaOpRight b) (Set (RTuple t)), (~) * (DyaOpLeft a) (Set (RTuple t1))) => a -> b -> DyaOpRes a b (Relation (HAppendListR * t1 t2)) -- | Cardinality. -- --
--   >>> (#) sp
--   12
--   
-- -- As count. (#) :: (MonOp a, (~) * (MonOpArg a) (Set a1)) => a -> MonOpRes a Int -- | Is member of. -- --
--   >>> let spX = rTuple(sno .=. "S3", qty .=. 200, pno .=. "P2")
--   
--   >>> spX ∈ sp
--   True
--   
-- -- As member. (∈) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => Record r -> a -> MonOpRes a Bool -- | Is not member of. -- --
--   >>> spX ∉ sp
--   False
--   
-- -- As notMember. (∉) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => Record r -> a -> MonOpRes a Bool -- | Is member of left. As (flip member). (∋) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => a -> Record r -> MonOpRes a Bool -- | Is not member of left. As (flip notMember). (∌) :: (Ord (HList l), HLabelSet [*] (LabelsOf l), HRearrange3 (LabelsOf l) r l, SameLength' * * r l, SameLength' * * r (LabelsOf l), SameLength' * * l r, SameLength' * * (LabelsOf l) r, MonOp a, (~) * (MonOpArg a) (Set (Record l))) => a -> Record r -> MonOpRes a Bool -- | The empty set. Note that this is neither tableDum nor -- tableDee. -- --
--   >>> (relation [] :: Relation '[]) == (∅)
--   True
--   
--   >>> relation [rTuple (sno .=. "S1", status .=. 5)] == (∅)
--   False
--   
(∅) :: Set a -- | Exports the pertinent parts of HaskRel building on HList records. This -- gives most features of the relational algebra, relation variable -- support, HList CommonMain, as well as certain non-relational features -- such as ordering. module Database.HaskRel.RDBMS -- | Relation variable reference. This type has a phantom type variable, -- which generally calls for the type to be explicity specified: -- --
--   s = Relvar "SuppliersPartsDB/S.rv" :: Relvar '[SNO, SName, Status, City]
--   
data Relvar (a :: [*]) Relvar :: FilePath -> Relvar [relvarPath] :: Relvar -> FilePath -- | Gives the type a relvar results in. Note that the value this results -- in will always be undefined. relvarType :: Relvar a -> Relation a -- | Read a relation variable from the file referenced by the first -- argument readRelvar :: (Ord (HList b), Read (HList (RecordValuesR b)), RecordValues b, HMapAux HList TaggedFn (RecordValuesR b) b) => Relvar b -> IO (Relation b)