-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Efficient relational queries on Haskell sets. -- -- Just pick which parts of your data structures you want indexed using -- an easy to use template-haskell function. Spare yourself the need to -- write, run, and maintain code that marshalls your data to/from an -- external relational database just for efficient queries. -- happstack-ixset relies on generics and TH to spare you the boilerplate -- normally required for such tasks. @package happstack-ixset @version 0.5.0.1 -- | This module defines typable indices and convenience functions. Should -- be probably considered private to Happstack.Data.IxSet. module Happstack.Data.IxSet.Ix -- | Ix is a Map from some Typeable key to a set of -- values for that key. Ix carries type information inside. data Ix a Ix :: (Map key (Set a)) -> Ix a -- | Convenience function for inserting into Maps of Sets as -- in the case of an Ix. If they key did not already exist in the -- Map, then a new Set is added transparently. insert :: (Ord a, Ord k) => k -> a -> Map k (Set a) -> Map k (Set a) -- | Convenience function for deleting from Maps of Sets If -- the resulting Set is empty, then the entry is removed from the -- Map. delete :: (Ord a, Ord k) => k -> a -> Map k (Set a) -> Map k (Set a) instance [overlap ok] Typeable1 Ix instance [overlap ok] (Data ctx a, Sat (ctx (Ix a))) => Data ctx (Ix a) instance [overlap ok] (Data a) => Data (Ix a) -- | Assume you have a type like: -- --
-- data Entry = Entry Author [Author] Updated Id Content -- newtype Updated = Updated EpochTime -- newtype Id = Id Int64 -- newtype Content = Content String -- newtype Author = Author Email -- type Email = String ---- -- 1. Decide what parts of your type you want indexed and make your type -- an instance of Indexable -- --
-- instance Indexable Entry () where -- empty = ixSet -- [ Ix (Map.empty::Map Author (Set Entry)) -- out of order -- , Ix (Map.empty::Map Id (Set Entry)) -- , Ix (Map.empty::Map Updated (Set Entry)) -- , Ix (Map.empty::Map Test (Set Entry)) -- bogus index -- , Ix (Map.empty::Map Word (Set Entry)) -- text index -- ] -- calcs entry = () -- words for text indexing purposes ---- -- 3. Use insert, delete, updateIx, deleteIx -- and empty to build up an IxSet collection -- -- entries = foldr insert empty [e1,e2,e3,e4] entries' = -- foldr delete entries [e1,e3] entries'' = update e4 e5 -- entries -- -- 4. Use the query functions below to grab data from it. e.g. -- --
-- entries @< (Updated t1) @= (Author "john@doe.com") ---- -- will find all items in entries updated earlier than t1 by -- john@doe.com. -- -- 5. Text Index -- -- If you want to do add a text index extract the words in entry and pass -- them in the calc method of the Indexable class. Then if you -- want all entries with either word1 or word2, you change the instance -- to -- --
-- getWords entry = let Just (Content s) = -- gGet entry in map Word $ words s ---- --
-- instance Indexable Entry [Word] where -- .... -- calcs entry = getWords entry ---- -- Now you can do this query to find entries with any of the words -- --
-- entries @+ [Word "word1",Word "word2"] ---- -- And if you want all entries with both: -- --
-- entries @* [Word "word1",Word "word2"] ---- -- 6. Find only the first author -- -- If an Entry has multiple authors and you want to be able to query on -- the first author, define a FirstAuthor datatype and add it to -- the result of calc. calc e = (toWords e, getFirstAuthor e) -- and now you can do -- --
-- newtype FirstAuthor = FirstAuthor Email ---- --
-- getFirstAuthor = let Just (Author a) = -- gGet Entry in FirstAuthor a ---- --
-- instance Indexable Entry ([Word],FirstAuthor) -- ... -- empty = .... -- Ix (Map.empty::Map FirstAuthor (Set Entry))] -- calcs entry = (getWords Entry,getFirstAuthor entry) -- -- entries @= (FirstAuthor "john@doe.com") -- guess what this does --module Happstack.Data.IxSet data IxSet a -- | Indexable class defines objects that can be members of -- IxSet. If you don't want calculated values use -- Indexable a (). class (Data b) => Indexable a b | a -> b empty :: (Indexable a b) => IxSet a calcs :: (Indexable a b) => a -> b -- | Function to be used for calcs in the case of an -- Indexable a () instance. noCalcs :: t -> () -- | Template Haskell helper function for automatically building an -- Indexable instance from a data type, e.g. -- --
-- data Foo = Foo Int String ---- -- and -- --
-- $(inferIxSet "FooDB" ''Foo 'noCalcs [''Int,''String]) ---- -- will build a type synonym -- --
-- type FooDB = IxSet Foo ---- -- with Int and String as indices. -- -- WARNING: The type specified as the first index must be a type which -- appears in all values in the IxSet or toList and -- toSet will not function properly. You will be warned not to do -- this by runtime error. You can always use the element type itself. For -- example: -- --
-- $(inferIxSet "FooDB" ''Foo 'noCalcs [''Foo, ''Int, ''String]) --inferIxSet :: String -> Name -> Name -> [Name] -> Q [Dec] -- | Create an IxSet using list of indices. Useful in -- Indexable empty method. ixSet :: [Ix a] -> IxSet a type IndexOp = forall k a. (Ord k, Ord a) => k -> a -> Map k (Set a) -> Map k (Set a) -- | Higher order operator for modifying IxSets. Use this when your -- final function should have the form a -> IxSet a -> IxSet -- a, e.g. insert or delete. change :: (Data a, Ord a, Data b, Indexable a b) => IndexOp -> a -> IxSet a -> IxSet a -- | Inserts an item into the IxSet. If your data happens to have -- primary key this function might not be what you want. See -- updateIx. insert :: (Data a, Ord a, Data b, Indexable a b) => a -> IxSet a -> IxSet a -- | Removes an item from the IxSet. delete :: (Data a, Ord a, Data b, Indexable a b) => a -> IxSet a -> IxSet a -- | Will replace the item with index k. Only works if there is at most one -- item with that index in the IxSet. Will not change IxSet -- if you have more then 1 item with given index. updateIx :: (Indexable a b, Ord a, Data a, Typeable k) => k -> a -> IxSet a -> IxSet a -- | Will delete the item with index k. Only works if there is at most one -- item with that index in the IxSet. Will not change IxSet -- if you have more then 1 item with given index. deleteIx :: (Indexable a b, Ord a, Data a, Typeable k) => k -> IxSet a -> IxSet a -- | Converts a Set to an IxSet. fromSet :: (Indexable a b, Ord a, Data a) => Set a -> IxSet a -- | Converts a list to an IxSet. fromList :: (Indexable a b, Ord a, Data a) => [a] -> IxSet a -- | Converts an IxSet to a Set of its elements. toSet :: (Ord a) => IxSet a -> Set a -- | Converts an IxSet to its list of elements. toList :: (Ord a) => IxSet a -> [a] -- | If the IxSet is a singleton it will return the one item stored -- in it. If IxSet is empty or has many elements this function -- returns Nothing. getOne :: (Ord a) => IxSet a -> Maybe a -- | Like getOne with a user provided default. getOneOr :: (Ord a) => a -> IxSet a -> a -- | Returns the number of unique items in the IxSet. size :: (Ord a) => IxSet a -> Int -- | Return True if the IxSet is empty, False -- otherwise. null :: IxSet a -> Bool -- | An infix intersection operation. (&&&) :: (Ord a, Data a, Indexable a b) => IxSet a -> IxSet a -> IxSet a -- | An infix union operation. (|||) :: (Ord a, Data a, Indexable a b) => IxSet a -> IxSet a -> IxSet a -- | Takes the union of the two IxSets. union :: (Ord a, Data a, Indexable a b) => IxSet a -> IxSet a -> IxSet a -- | Takes the intersection of the two IxSets. intersection :: (Ord a, Data a, Indexable a b) => IxSet a -> IxSet a -> IxSet a -- | Infix version of getEQ. (@=) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> k -> IxSet a -- | Infix version of getLT. (@<) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> k -> IxSet a -- | Infix version of getGT. (@>) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> k -> IxSet a -- | Infix version of getLTE. (@<=) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> k -> IxSet a -- | Infix version of getGTE. (@>=) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> k -> IxSet a -- | Returns the subset with indices in the open interval (k,k). (@><) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> (k, k) -> IxSet a -- | Returns the subset with indices in [k,k). (@>=<) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> (k, k) -> IxSet a -- | Returns the subset with indices in (k,k]. (@><=) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> (k, k) -> IxSet a -- | Returns the subset with indices in [k,k]. (@>=<=) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> (k, k) -> IxSet a -- | Creates the subset that has an index in the provided list. (@+) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> [k] -> IxSet a -- | Creates the subset that matches all the provided indices. (@*) :: (Indexable a b, Data a, Ord a, Typeable k) => IxSet a -> [k] -> IxSet a -- | Returns the subset with an index equal to the provided key. The set -- must be indexed over key type, doing otherwise results in runtime -- error. getEQ :: (Indexable a b, Data a, Ord a, Typeable k) => k -> IxSet a -> IxSet a -- | Returns the subset with an index less than the provided key. The set -- must be indexed over key type, doing otherwise results in runtime -- error. getLT :: (Indexable a b, Data a, Ord a, Typeable k) => k -> IxSet a -> IxSet a -- | Returns the subset with an index greater than the provided key. The -- set must be indexed over key type, doing otherwise results in runtime -- error. getGT :: (Indexable a b, Data a, Ord a, Typeable k) => k -> IxSet a -> IxSet a -- | Returns the subset with an index less than or equal to the provided -- key. The set must be indexed over key type, doing otherwise results in -- runtime error. getLTE :: (Indexable a b, Data a, Ord a, Typeable k) => k -> IxSet a -> IxSet a -- | Returns the subset with an index greater than or equal to the provided -- key. The set must be indexed over key type, doing otherwise results in -- runtime error. getGTE :: (Indexable a b, Data a, Ord a, Typeable k) => k -> IxSet a -> IxSet a -- | Returns the subset with an index within the interval provided. The -- bottom of the interval is closed and the top is open, i. e. [k1;k2). -- The set must be indexed over key type, doing otherwise results in -- runtime error. getRange :: (Indexable a b, Typeable k, Ord a, Data a) => k -> k -> IxSet a -> IxSet a -- | Returns lists of elements paired with the indices determined by type -- inference. groupBy :: (Typeable k, Typeable t) => IxSet t -> [(k, [t])] -- | A function for building up selectors on IxSets. Used in the -- various get* functions. The set must be indexed over key type, doing -- otherwise results in runtime error. getOrd :: (Indexable a b, Ord a, Data a, Typeable k) => Ordering -> k -> IxSet a -> IxSet a -- | Statistics about IxSet. This function returns quadruple -- consisting of 1. total number of elements in the set 2. number of -- declared indices 3. number of keys in all indices 4. number of values -- in all keys in all indices. This can aid you in debugging and -- optimisation. stats :: (Ord a) => IxSet a -> (Int, Int, Int, Int) instance [overlap ok] Typeable1 IxSet instance [overlap ok] (Data a) => Data (IxSet a) instance [overlap ok] (Indexable a b, Data a, Ord a) => Monoid (IxSet a) instance [overlap ok] (Ord a, Read a, Data a, Indexable a b) => Read (IxSet a) instance [overlap ok] (Ord a, Show a) => Show (IxSet a) instance [overlap ok] (Indexable a b, Data a, Ord a, Default a) => Default (IxSet a) instance [overlap ok] (Data ctx a, Sat (ctx (IxSet a)), Sat (ctx [a]), Indexable a b, Data a, Ord a) => Data ctx (IxSet a) instance [overlap ok] (Serialize a, Ord a, Data a, Indexable a b) => Serialize (IxSet a) instance [overlap ok] Version (IxSet a) instance [overlap ok] (Eq a, Ord a, Typeable a) => Ord (IxSet a) instance [overlap ok] (Eq a, Ord a, Typeable a) => Eq (IxSet a)