HaskRel-0.1.0.0: src/Database/HaskRel/Relational/Variable.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE UndecidableInstances, FlexibleContexts, ScopedTypeVariables #-}
{-|
Module : Database.HaskRel.Relational.Variable
Description : Relation variable definition and support functions
Copyright : © Thor Michael Støre, 2015
License : GPL v2 without "any later version" clause
Maintainer : thormichael át gmail døt com
Stability : experimental
Relation variable definition, along with IO level support functions.
-}
module Database.HaskRel.Relational.Variable (
-- * Relation variable definitions
Relvar (Relvar, relvarPath), relvarType,
-- * Relational input
readRel, readRelvar, hListsToRel,
-- * Relational output
writeRelvarBody, writeRelvarBody', showRelStr
) where
import Data.HList.CommonMain
import Data.Set ( Set, fromList )
import Data.Typeable ( Typeable )
import Database.HaskRel.HFWTabulation
( HFWPresent, HPresentTypedRecAttr, HPresentRecAttr, showHListSetType,
hfwPrint, hfwPrintTyped, hfwPrintTypedTS )
import Database.HaskRel.Relational.Definition ( Relation, bodyAsList )
-- == Relation variable reference == --
{-| 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 { relvarPath :: FilePath }
-- | Gives the type a relvar results in. Note that the value this results in will always be @undefined@.
relvarType :: Relvar a -> Relation a
relvarType rv = undefined
-- TODO: It should be enforced that a given relvar has a given type
-- TODO: This is also afflicted by the issue that showHListSetType was developed for TIPs
instance Typeable a => Show ( Relvar a ) where
show a = "Relvar \"" ++ relvarPath a ++ "\" :: Relvar" ++ showHListSetType ( relvarType a )
-- | 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
hListsToRel = fromList . map hMapTaggedFn
{-| 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 :: forall b .
(Ord (HList b), Read (HList (RecordValuesR b)), RecordValues b,
HMapAux HList TaggedFn (RecordValuesR b) b) =>
String -> Relation b
readRel s = hListsToRel $ read $ "[" ++ s ++ "]"
-- | Reads a relation value of a given type from a string.
readRel' :: forall b .
(Ord (HList b), Read (HList (RecordValuesR b)), RecordValues b,
HMapAux HList TaggedFn (RecordValuesR b) b) =>
String -> Relation b -> Relation b
readRel' s rt = hListsToRel $ read $ "[" ++ s ++ "]"
-- | 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)
readRelvar rv = do
relStr <- readFile ( relvarPath rv )
return $ readRel relStr
-- | Prints a relation as a list without the outer brackets.
showRelStr :: (Show (HList (RecordValuesR r)), RecordValues r) =>
Relation r -> String
showRelStr = init . tail . show . bodyAsList
-- TODO: This uses text-processing on the result of a call to show, fix so that
-- it doesn't break if the show-format is changed.
-- | Writes a body of a relvar to a given file
writeRelvarBody :: Show r => FilePath -> r -> IO ()
writeRelvarBody n hll = writeFile n ( init $ tail $ show hll )
-- | Writes a body of a relvar to a given relvar file reference
writeRelvarBody' :: Show r => Relvar rv -> r -> IO ()
writeRelvarBody' rv hll = writeFile ( relvarPath rv ) ( init $ tail $ show hll )
-- == HFWPresent instance for relvars
instance (Ord (HList b), Read (HList (RecordValuesR b)), Typeable b,
RecordValues b, HMapAux HList TaggedFn (RecordValuesR b) b,
HFoldr (Mapcar HPresentTypedRecAttr) [[String]] (RecordValuesR b) [[String]],
HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR b) [[String]]) =>
HFWPresent ( Relvar b )
where
hfwPrint r' = do
r <- readRelvar r'
hfwPrint r
hfwPrintTypedTS ts r' = do
r <- readRelvar r'
hfwPrintTypedTS ts r