raft-0.3.2.2: src/Data/Relational/Lists.hs
-----------------------------------------------------------------------------
--
-- Module : Data.Relational.Lists
-- Copyright : (c) 2015-16 Brian W Bush
-- License : MIT
--
-- Maintainer : Brian W Bush <consult@brianwbush.info>
-- 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))