-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Query SQL databases using Nested Relational Calculus embedded in Haskell. -- -- Query SQL databases using Nested Relational Calculus embedded in -- Haskell. @package narc @version 0.1 module Narc.Util sortAlist :: [(String, b)] -> [(String, b)] -- | shadow: given two alists, return the elements of the first that are -- NOT mapped by the second -- -- Tests that an alist or environment is well-formed: that its first | -- components are all unique. onCorresponding :: Ord a => ([b] -> c) -> [(a, b)] -> [c] intSqrt :: Integral a => a -> a disjoint :: Eq a => [a] -> [a] -> Bool -- | Convert a maybe to a zero-or-one-element list. asList :: Maybe a -> [a] isRight :: Either a b -> Bool isLeft :: Either a b -> Bool -- | zipAlist: given two alists with the same domain, returns an alist -- mapping each of those domain values to the pair of the two -- corresponding values from the given lists. -- -- mapstrcat: transform a list to one of strings, with a given | -- function, and join these together with some glue string. mapstrcat :: String -> (a -> String) -> [a] -> String module Narc.Common type Tabname = String type Field = String module Narc.Pretty class Pretty t pretty :: Pretty t => t -> String module Narc.Failure type Failure a = Either String a runError :: Either String t -> t type ErrorGensym a = ErrorT String Gensym a instance Error () module Narc.Failure.QuickCheck failureToProperty :: Testable a => Failure a -> Property failureToPropertyIgnoreFailure :: Testable a => Failure a -> Property module Narc.Type type TyVar = Int data Type TBool :: Type TNum :: Type TString :: Type TUnit :: Type TList :: Type -> Type TArr :: Type -> Type -> Type TRecord :: [(String, Type)] -> Type TVar :: TyVar -> Type type QType = ([TyVar], Type) type TySubst = [(Int, Type)] type TyEnv = [(Var, QType)] emptyTySubst :: TySubst -- | ftvs: free type variables -- -- ftvsSubst: the free type variables of a type substitution--that is, -- the type variables free in the types in the range of the substitution. -- -- occurs x ty: does variable x appear in type ty? (Note there are no -- type-variable binders). applyTySubst :: TySubst -> Type -> Type -- | normalizeType: Renumber all the type variables in a normal way to -- allow comparing types. normalizeType :: Type -> State (Int, [(Int, Int)]) Type instanceOf :: Type -> Type -> Failure () unify :: Type -> Type -> Failure (TySubst) unifyAll :: [Type] -> Failure TySubst composeTySubst :: [TySubst] -> Failure TySubst disjoinSubst :: TySubst -> TySubst -> TySubst instance Eq Type instance Show Type instance Arbitrary Type module Narc.AST -- | Terms in the nested relational calculus (represented concretely | with -- named variables) data Term' a Unit :: Term' a Bool :: Bool -> Term' a Num :: Integer -> Term' a String :: String -> Term' a PrimApp :: String -> [Term a] -> Term' a Var :: Var -> Term' a Abs :: Var -> (Term a) -> Term' a App :: (Term a) -> (Term a) -> Term' a Table :: Tabname -> [(Field, Type)] -> Term' a If :: (Term a) -> (Term a) -> (Term a) -> Term' a Singleton :: (Term a) -> Term' a Nil :: Term' a Union :: (Term a) -> (Term a) -> Term' a Record :: [(String, Term a)] -> Term' a Project :: (Term a) -> String -> Term' a Comp :: Var -> (Term a) -> (Term a) -> Term' a -- | Terms whose every subexpression is annotated with a value of some | -- particular type. type Term a = (Term' a, a) type Var = String type PlainTerm = Term () type TypedTerm = Term Type fvs :: (Term' t, t) -> [Var] -- | substTerm x v m: substite v for x in term m (Actually incorrect -- because it does not make substitutions in the q.) substTerm :: Var -> Term t -> Term t -> Term t strip :: Term a -> Term () retagulate :: (Term a -> a) -> Term a -> Term a rename :: Var -> Var -> (Term' a, a) -> (Term' a, a) variables :: [[Char]] (!) :: t -> (t, ()) unit_ :: (Term' a, ()) class Const a cnst_ :: Const a => a -> Term () primApp_ :: String -> [Term a] -> (Term' a, ()) var_ :: Var -> (Term' a, ()) abs_ :: Var -> Term a -> (Term' a, ()) app_ :: Term a -> Term a -> (Term' a, ()) table_ :: Tabname -> [(Field, Type)] -> (Term' a, ()) ifthenelse_ :: Term a -> Term a -> Term a -> (Term' a, ()) singleton_ :: Term a -> (Term' a, ()) nil_ :: (Term' a, ()) union_ :: Term a -> Term a -> (Term' a, ()) record_ :: [(String, Term a)] -> (Term' a, ()) project_ :: Term a -> String -> (Term' a, ()) foreach_ :: Term a -> Var -> Term a -> (Term' a, ()) instance Eq a => Eq (Term' a) instance Show a => Show (Term' a) instance Const Integer instance Const Bool instance NarcSem (Term' (), ()) instance Constable Integer instance Constable Bool module Narc.Eval type Env = [(Var, Value)] data Value VUnit :: Value VBool :: Bool -> Value VNum :: Integer -> Value VList :: [Value] -> Value VRecord :: [(String, Value)] -> Value VAbs :: Var -> TypedTerm -> Env -> Value fromValue :: Value -> TypedTerm initialEnv :: Env -- | appPrim: apply a primitive function to a list of value arguments. appPrim :: String -> [Value] -> Value -- | eval: Evaluate a typed term in a closing environment. Captures the -- effects performed by the term. (NB: type info is not actually used; -- should eliminate this.) eval :: Env -> TypedTerm -> Value instance Eq Value instance Show Value module Narc.AST.Pretty instance Pretty (Term a) instance Pretty (Term' a) module Narc.SQL data Op Eq :: Op Less :: Op Plus :: Op Minus :: Op Times :: Op Divide :: Op data UnOp Min :: UnOp Max :: UnOp Count :: UnOp Sum :: UnOp Average :: UnOp -- | Query: the type of SQL queries (select R from Ts where B) (This -- is unpleasant; it should probably be organized into various syntactic -- classes.) data Query Select :: Query -> [(Field, Field, Type)] -> [Query] -> Query rslt :: Query -> Query tabs :: Query -> [(Field, Field, Type)] cond :: Query -> [Query] QNum :: Integer -> Query QBool :: Bool -> Query QNot :: Query -> Query QOp :: Query -> Op -> Query -> Query QField :: String -> String -> Query QRecord :: [(Field, Query)] -> Query QUnion :: Query -> Query -> Query QIf :: Query -> Query -> Query -> Query QExists :: Query -> Query -- | sizeQuery approximates the size of a query by calling giving -- up | its node count past a certain limit (currently limit = 100, -- below). sizeQueryExact :: Query -> Integer -- | sizeQuery approximates the size of a query by calling giving -- up | its node count past a certain limit (currently limit = 100, -- below). sizeQuery :: Query -> Integer -- | a groundQuery is a *real* SQL query--one without variables or appl'ns. groundQuery :: Query -> Bool -- | a groundQueryExpr is an atomic-type expression. groundQueryExpr :: Query -> Bool serialize :: Query -> String instance Eq Op instance Show Op instance Eq UnOp instance Show UnOp instance Eq Query instance Show Query module Narc.SQL.Pretty instance Pretty Op instance Pretty Query module Narc.TypeInfer -- | tyCheck env term infers a type for term in environment env. The -- environment has type [(Var, QType)]; an entry (x, qty) indicates that -- variable x has the quantified type qty; a QType (ys, ty) indicates the -- type forall ys, ty. tyCheck :: TyEnv -> Term a -> ErrorGensym (TySubst, Term Type) typeAnno :: Term Type -> Type makeInitialTyEnv :: ErrorGensym [(String, QType)] infer :: Term a -> ErrorGensym TypedTerm infer' :: Term' a -> ErrorGensym TypedTerm inferTys :: Term () -> ErrorGensym Type inferType :: Term () -> ErrorGensym Type inferType' :: Term' () -> ErrorGensym Type module Narc.Compile compile :: TyEnv -> TypedTerm -> Query module Narc.HDBC run :: IConnection conn => Term a -> conn -> IO [[SqlValue]] module Narc.Rewrite perhaps :: (a -> Maybe a) -> a -> a bu :: (Term a -> Maybe (Term a)) -> Term a -> Term a module Narc.Test makeNormalizerTests :: ErrorGensym Test unitTests :: ErrorGensym Test runUnitTests :: IO Counts -- | Assertion that well-typed terms evaluate without throwing. prop_eval_safe :: Property prop_typedTermGen_tyCheck :: Property main :: IO () -- | Query SQL databases using Nested Relational Calculus embedded in -- Haskell. -- -- The primed functions in this module are in fact the syntactic forms of -- the embedded language. Use them as, for example: -- --
-- foreach (table "employees" []) $ \emp -> -- having (primApp "<" [cnst 20000, project emp "salary"]) $ -- singleton (record [(project emp "name")]) --module Narc type NarcTerm = Gensym (Term ()) -- | Translate a Narc term to an SQL query. narcTermToSQL :: NarcTerm -> Query -- | A dummy value, or zero-width record. unit :: NarcTerm class Const a -- | Apply some primitive function, such as (+) or avg, -- to a list of arguments. primApp :: String -> [NarcTerm] -> NarcTerm -- | Create a functional abstraction. abs :: (String -> NarcTerm) -> NarcTerm -- | Apply a functional term to an argument. app :: NarcTerm -> NarcTerm -> NarcTerm -- | A condition between two terms, as determined by the boolean value of -- the first term. ifthenelse :: NarcTerm -> NarcTerm -> NarcTerm -> NarcTerm -- | A singleton collection of one item. singleton :: NarcTerm -> NarcTerm -- | An empty collection. nil :: NarcTerm -- | The union of two collections union :: NarcTerm -> NarcTerm -> NarcTerm -- | Construct a record (name-value pairs) out of other terms; usually -- used, with base values for the record elements, as the final result of -- a query, corresponding to the select clause of a SQL query, -- but can also be used with nested results internally in a query. record :: [(String, NarcTerm)] -> NarcTerm -- | Project a field out of a record value. project :: NarcTerm -> String -> NarcTerm -- | For each item in the collection resulting from the first argument, -- give it to the function which is the second argument and -- evaluate--this corresponds to a loop, or two one part of a cross in -- traditional SQL queries. foreach :: NarcTerm -> (NarcTerm -> NarcTerm) -> NarcTerm -- | Filter the current iteration as per the condition in the first -- argument. Corresponds to a where clause in a SQL query. having :: NarcTerm -> NarcTerm -> NarcTerm instance Const' Integer instance Const' Bool