----------------------------------------------------------------------------- -- -- Module : Data.Relational.Lists -- Copyright : (c) 2015-16 Brian W Bush -- License : MIT -- -- Maintainer : Brian W Bush -- Stability : Experimental -- Portability : Portable -- -- | Tuples and relations as lists. -- ----------------------------------------------------------------------------- {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-deprecations #-} module Data.Relational.Lists {-# DEPRECATED "This module will be replaced in a future release." #-} ( -- * Types Tabulation , Record(..) , Table(..) -- * Input/Output , readTable , writeTable , makeTable ) where import Control.Monad (guard, msum) import Data.Binary (Binary(..)) import Data.Default (Default(..)) import Data.List (union) import Data.List.Util.Listable (readTabbedListsWithHeader, writeTabbedListsWithHeader) import Data.String.Util (Stringy) import Data.Relational (Relation(..), Tuple(..)) -- | A tabulation. type Tabulation a = Table (Record a) -- | A record. newtype Record a = Record {unRecord :: [a]} deriving (Eq, Read, Show) instance Tuple (Record a) where type Attribute (Record a) = a makeTuple = Record attributes = unRecord instance Functor Record where fmap f = Record . fmap f . unRecord instance Foldable Record where foldMap f = foldMap f . unRecord instance Binary a => Binary (Record a) where put = put . unRecord get = Record <$> get -- | A table. data Table r = Table { header :: [String] -- ^ The header. , records :: [r] -- ^ The records. } instance Tuple r => Relation String r (Table r) where names = header empty = flip Table [] makeRelation = Table tuples = records attributeMaybe Table{..} name = msum . zipWith (\n a -> guard (n == name) >> return a) header . attributes instance Functor Table where fmap f Table{..} = Table header $ fmap f records instance Foldable Table where foldMap f Table{..} = foldMap f records instance (Monoid (Attribute r), Tuple r) => Monoid (Table r) where mempty = Table [] [] mappend x y = let header' = header x `union` header y makePadder ns = let pattern = map (`elem` ns) header' pad (False : us) vs = mempty : pad us vs pad (True : us) (v : vs) = v : pad us vs pad [] _ = [] pad _ [] = [] in makeTuple . pad pattern . attributes in Table header' $ map (makePadder $ header x) (records x) ++ map (makePadder $ header y) (records y) instance (Read (Attribute r), Tuple r) => Read (Table r) where readsPrec p = readParen (p > 10) $ \ r -> do ("fromLists", s) <- lex r (ns, t) <- reads s (rs, u) <- reads t return (Table ns $ map makeTuple rs, u) instance (Show (Attribute r), Tuple r) => Show (Table r) where show Table{..} = "fromLists " ++ show header ++ " " ++ show (map attributes records) instance Binary r => Binary (Table r) where put Table{..} = put (header, records) get = uncurry Table <$> get -- | Read a table. readTable :: (Stringy (Attribute r), Tuple r) => FilePath -- ^ The file path. -> IO (Table r) -- ^ Action to read the table. readTable = readTabbedListsWithHeader -- | Write a table. writeTable :: (Stringy (Attribute r), Tuple r) => FilePath -- ^ The file path. -> Table r -- ^ The table. -> IO () -- ^ Action to write the table. writeTable = writeTabbedListsWithHeader -- | Make a table. makeTable :: forall r . (Default (Table r), Tuple r) => [r] -- ^ The records. -> Table r -- ^ The table. makeTable = makeRelation (header (def :: Table r))