module Data.Relational.Value (
Value(..)
, asValue
, valueAsRealFloat
, asRealFloat
, valueAsString
, string
, number
, number'
, enum
, valueAsEnum
, readTable
, writeTable
) where
import Control.Applicative ((<|>))
import Data.Aeson.Types (ToJSON(..), Value(..))
import Data.Default.Util (nan)
import Data.Maybe (fromMaybe)
import Data.Maybe.Util (maybeRead)
import Data.Relational (Tuple(..))
import Data.Relational.Lists (Table(..), Tabulation)
import Data.Scientific (fromFloatDigits)
import Data.Text (pack, unpack)
import qualified Data.Relational.Lists as Lists (readTable, writeTable)
asValue :: String
-> Value
asValue s =
let
n = if null s then Just Null else Nothing
b = toJSON <$> (maybeRead s :: Maybe Bool)
x = toJSON <$> (maybeRead s :: Maybe Double)
in
fromMaybe (toJSON s) $ n <|> b <|> x
valueAsRealFloat :: RealFloat a => Value -> a
valueAsRealFloat (Number x) = realToFrac x
valueAsRealFloat _ = nan
asRealFloat :: (RealFloat a, Read a) => String -> a
asRealFloat = fromMaybe nan . maybeRead
valueAsString :: Value -> String
valueAsString Null = ""
valueAsString (Bool b ) = show b
valueAsString (Number x) = show x
valueAsString (String s) = unpack s
valueAsString x = show x
string :: String -> Value
string = String . pack
number :: RealFloat a => a -> Value
number = Number . fromFloatDigits
number' :: String -> Value
number' = number . (read :: String -> Double)
enum :: (Enum a, Show a) => a -> Value
enum = string . show
valueAsEnum :: (Enum a, Read a) => Value -> a
valueAsEnum = read . valueAsString
readTable :: (Attribute r ~ Value, Tuple r)
=> FilePath
-> IO (Table r)
readTable path =
fmap (makeTuple . fmap asValue . attributes)
<$> (Lists.readTable path :: IO (Tabulation String))
writeTable :: (Attribute r ~ Value, Tuple r)
=> FilePath
-> Table r
-> IO ()
writeTable path x =
Lists.writeTable path
(fmap (makeTuple . fmap valueAsString . attributes) x :: Tabulation String)