{-|
This module contains the definition of `Value`, `Table`, and `Column`, classes over them, and functions for manipulation of them.
-}
module Lsql.Csv.Core.Tables
  (
    Table(Table), Column(Column),
    Value(IntValue, StringValue, DoubleValue, BoolValue), 

    buildTable, crossJoinTable, filterTable, sortTable, byTable,
    emptyTable, 

    columnNames, columnValue, showColumn,
    applyOp, applyInOp,

    Boolable(getBool)
  )
where

import Data.List

-- | Class for converting a value to a `Bool`
class Boolable a where
  getBool :: a -> Bool

-- | The representation of data in `Table`s
data Value = IntValue Int | StringValue String | DoubleValue Double | BoolValue Bool

instance Boolable Value where
  getBool :: Value -> Bool
getBool (IntValue Int
v) = Int
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
  getBool (DoubleValue Double
d) = String -> Bool
forall a. HasCallStack => String -> a
error(String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
"Double " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
d String -> String -> String
forall a. [a] -> [a] -> [a]
++String
" can't be converted to bool."
  getBool (BoolValue Bool
b) = Bool
b
  getBool (StringValue String
s)
   | String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"true" = Bool
True
   | String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"false" = Bool
False
   | Bool
otherwise = String -> Bool
forall a. HasCallStack => String -> a
error(String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
"String " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" can't be converted to bool."

instance Ord Value where
  (IntValue Int
a) <= :: Value -> Value -> Bool
<= (IntValue Int
b) = Int
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
b
  (DoubleValue Double
a) <= (IntValue Int
b) = Double
a Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b
  (IntValue Int
a) <= (DoubleValue Double
b) = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
b
  (DoubleValue Double
a) <= (DoubleValue Double
b) = Double
a Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
b
  Value
a <= Value
b = (Value -> String
forall a. Show a => a -> String
show Value
a) String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= (Value -> String
forall a. Show a => a -> String
show Value
b)

instance Eq Value where
  (IntValue Int
a) == :: Value -> Value -> Bool
== (BoolValue Bool
b) = Bool
b Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== (Int
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0)
  (StringValue String
a) == (BoolValue Bool
b) = String
a String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> String
forall a. Show a => a -> String
show Bool
b

  (IntValue Int
a) == (IntValue Int
b) = Int
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
b
  (StringValue String
a) == (StringValue String
b) = String
a String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
b
  (BoolValue Bool
a) == (BoolValue Bool
b) = Bool
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
b
  (DoubleValue Double
a) == (DoubleValue Double
b) = Double
a Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
b

  Value
_ == Value
_ = Bool
False

instance Real Value where
  toRational :: Value -> Rational
toRational (IntValue Int
a) = Int -> Rational
forall a. Real a => a -> Rational
toRational Int
a
  toRational (DoubleValue Double
a) = Double -> Rational
forall a. Real a => a -> Rational
toRational Double
a
  toRational Value
x = String -> Rational
forall a. HasCallStack => String -> a
error(String -> Rational) -> String -> Rational
forall a b. (a -> b) -> a -> b
$ String
"Aritmetic operations with non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

instance RealFrac Value where
  properFraction :: forall b. Integral b => Value -> (b, Value)
properFraction (IntValue Int
a) = (Int -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a, Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int
0)
  properFraction (DoubleValue Double
a) = 
    let (b
n,Double
f) = Double -> (b, Double)
forall b. Integral b => Double -> (b, Double)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Double
a in
    (b
n, Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
f)

  properFraction Value
x = String -> (b, Value)
forall a. HasCallStack => String -> a
error(String -> (b, Value)) -> String -> (b, Value)
forall a b. (a -> b) -> a -> b
$ String
"Aritmetic operations with non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

instance Enum Value where
  toEnum :: Int -> Value
toEnum Int
a = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a. Enum a => Int -> a
toEnum Int
a

  fromEnum :: Value -> Int
fromEnum (IntValue Int
a) = Int -> Int
forall a. Enum a => a -> Int
fromEnum Int
a
  fromEnum Value
x = String -> Int
forall a. HasCallStack => String -> a
error(String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
"Integer operations with non-integer " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."


instance Integral Value where
  toInteger :: Value -> Integer
toInteger (IntValue Int
a) = Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
a
  toInteger Value
x = String -> Integer
forall a. HasCallStack => String -> a
error(String -> Integer) -> String -> Integer
forall a b. (a -> b) -> a -> b
$ String
"Integer operations on non-integer " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  quotRem :: Value -> Value -> (Value, Value)
quotRem (IntValue Int
a) (IntValue Int
b) =
    let (Int
x,Int
y) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
a Int
b in
    (Int -> Value
IntValue Int
x, Int -> Value
IntValue Int
y)

  quotRem Value
x Value
y = String -> (Value, Value)
forall a. HasCallStack => String -> a
error(String -> (Value, Value)) -> String -> (Value, Value)
forall a b. (a -> b) -> a -> b
$ String
"Integer operations on non-integer " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" or " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
y String -> String -> String
forall a. [a] -> [a] -> [a]
++String
" is not supported."

instance Num Value where
  (IntValue Int
a) + :: Value -> Value -> Value
+ (IntValue Int
b) = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
b
  (DoubleValue Double
a) + (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b
  (IntValue Int
a) + (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b
  (DoubleValue Double
a) + (IntValue Int
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b
  Value
x + Value
y = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"+ operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" or " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
y String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  (IntValue Int
a) * :: Value -> Value -> Value
* (IntValue Int
b) = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
b
  (DoubleValue Double
a) * (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b
  (IntValue Int
a) * (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
b
  (DoubleValue Double
a) * (IntValue Int
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b
  Value
x * Value
y = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"* operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" or " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
y String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  abs :: Value -> Value
abs (IntValue Int
a) = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a. Num a => a -> a
abs Int
a
  abs (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Num a => a -> a
abs Double
a
  abs Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"abs operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  signum :: Value -> Value
signum (IntValue Int
a) = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a. Num a => a -> a
signum Int
a
  signum (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Num a => a -> a
signum Double
a
  signum Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"signum operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  fromInteger :: Integer -> Value
fromInteger Integer
a = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
a

  negate :: Value -> Value
negate (IntValue Int
a) = Int -> Value
IntValue(Int -> Value) -> Int -> Value
forall a b. (a -> b) -> a -> b
$ -Int
a
  negate (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ -Double
a
  negate Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"negate operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

instance Fractional Value where
  (IntValue Int
a) / :: Value -> Value -> Value
/ (IntValue Int
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$
    (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a :: Double) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b :: Double)

  (DoubleValue Double
a) / (IntValue Int
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b :: Double)
  (IntValue Int
a) / (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a :: Double) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
b
  (DoubleValue Double
a) / (DoubleValue Double
b) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
aDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
b

  fromRational :: Rational -> Value
fromRational Rational
a = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
a

instance Floating Value where
  pi :: Value
pi = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double
forall a. Floating a => a
pi

  exp :: Value -> Value
exp (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
exp Double
a
  exp (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
exp(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  exp Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"exp operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  log :: Value -> Value
log (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
log Double
a
  log (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
log(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  log Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"log operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  sin :: Value -> Value
sin (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
sin Double
a
  sin (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
sin(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  sin Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"sin operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  cos :: Value -> Value
cos (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
cos Double
a
  cos (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
cos(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  cos Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"cos operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  asin :: Value -> Value
asin (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
asin Double
a
  asin (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
asin(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  asin Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"asin operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  acos :: Value -> Value
acos (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
acos Double
a
  acos (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
acos(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  acos Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"acos operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  atan :: Value -> Value
atan (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
atan Double
a
  atan (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
atan(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  atan Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"atan operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  sinh :: Value -> Value
sinh (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
sinh Double
a
  sinh (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
sinh(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  sinh Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"sinh operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  asinh :: Value -> Value
asinh (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
asinh Double
a
  asinh (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
asinh(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  asinh Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"asinh operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  cosh :: Value -> Value
cosh (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
cosh Double
a
  cosh (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
cosh(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  cosh Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"cosh operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

  acosh :: Value -> Value
acosh (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
acosh Double
a
  acosh (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
acosh(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  acosh Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"acosh operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."
  
  atanh :: Value -> Value
atanh (DoubleValue Double
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
atanh Double
a
  atanh (IntValue Int
a) = Double -> Value
DoubleValue(Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a. Floating a => a -> a
atanh(Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a
  atanh Value
x = String -> Value
forall a. HasCallStack => String -> a
error(String -> Value) -> String -> Value
forall a b. (a -> b) -> a -> b
$ String
"atanh operation on non-number " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Value -> String
forall a. Show a => a -> String
show Value
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not supported."

instance Show Value where
  show :: Value -> String
show (IntValue Int
v) = Int -> String
forall a. Show a => a -> String
show Int
v
  show (StringValue String
v) = String
v
  show (DoubleValue Double
v) = Double -> String
forall a. Show a => a -> String
show Double
v
  show (BoolValue Bool
True) = String
"true"
  show (BoolValue Bool
False) = String
"false"

-- | A single column of a table
data Column = Column 
  [String] -- ^ The names of the column
  [Value] -- ^ The values of the column

instance Eq Column where
  (Column [String]
_ [Value]
a) == :: Column -> Column -> Bool
== (Column [String]
_ [Value]
b) = [Value]
a [Value] -> [Value] -> Bool
forall a. Eq a => a -> a -> Bool
== [Value]
b

instance Ord Column where
  (Column [String]
_ [Value]
a) <= :: Column -> Column -> Bool
<= (Column [String]
_ [Value]
b) = [Value]
a [Value] -> [Value] -> Bool
forall a. Ord a => a -> a -> Bool
<= [Value]
b

instance Show Column where
  show :: Column -> String
show (Column [String]
_ [Value]
a) = [Value] -> String
forall a. Show a => a -> String
show [Value]
a


-- | A function for applying a two-argument function to two `Column`s
applyInOp:: (Value -> Value -> Value) -> Column -> Column -> Column
applyInOp :: (Value -> Value -> Value) -> Column -> Column -> Column
applyInOp Value -> Value -> Value
op (Column [String]
_ [Value]
a) (Column [String]
_ [Value]
b) = ([String] -> [Value] -> Column
Column [String
"comp"] (((Value, Value) -> Value) -> [(Value, Value)] -> [Value]
forall a b. (a -> b) -> [a] -> [b]
map (\(Value
x,Value
y) -> Value -> Value -> Value
op Value
x Value
y)([(Value, Value)] -> [Value]) -> [(Value, Value)] -> [Value]
forall a b. (a -> b) -> a -> b
$ [Value] -> [Value] -> [(Value, Value)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Value]
a [Value]
b))


-- | A function for applying a single argument function to a `Column`
applyOp:: (Value -> Value) -> Column -> Column
applyOp :: (Value -> Value) -> Column -> Column
applyOp Value -> Value
op (Column [String]
_ [Value]
a) = ([String] -> [Value] -> Column
Column [String
"comp"] ((Value -> Value) -> [Value] -> [Value]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Value
op [Value]
a))


-- | A single table of data
data Table = 
  Table 
  [String] -- ^ The table names 
  [Column] -- ^ The columns of the table

instance Show Table where
  show :: Table -> String
show (Table [String]
_ [Column]
a) = [Column] -> String
forall a. Show a => a -> String
show [Column]
a

-- | Converts `Column` to the list of `String` from its data.
showColumn :: Column -> [String]
showColumn :: Column -> [String]
showColumn (Column [String]
_ [Value]
col) =
  (Value -> String) -> [Value] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Value -> String
forall a. Show a => a -> String
show [Value]
col

-- | Returns all names of a `Column`.
columnName :: Column -> [String]
columnName :: Column -> [String]
columnName (Column [String]
names [Value]
_ ) = [String]
names

-- | Returns all values of a `Column`.
columnValue :: Column -> [Value]
columnValue :: Column -> [Value]
columnValue (Column [String]
_ [Value]
values ) = [Value]
values

-- | Returns pairs of names of `Column` and `Column` itself of the table.
columnNames :: Table -> [([String], Column)]
columnNames :: Table -> [([String], Column)]
columnNames (Table [String]
_ [Column]
cols) =
  let names :: [[String]]
names = (Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
cols in
  [[String]] -> [Column] -> [([String], Column)]
forall a b. [a] -> [b] -> [(a, b)]
zip [[String]]
names [Column]
cols


-- | Makes a table out of rows of `Value`.
buildTable :: 
       [String] -- ^ The names of the table
    -> [[String]] -- ^ The names of the columns
    -> [[Value]] -- ^ The rows of the table
    -> Table -- ^ The result table

buildTable :: [String] -> [[String]] -> [[Value]] -> Table
buildTable [String]
table_names [[String]]
names [[Value]]
in_data =
  if [[Value]]
in_data [[Value]] -> [[Value]] -> Bool
forall a. Eq a => a -> a -> Bool
/= [] then
    [String] -> [Column] -> Table
Table [String]
table_names [Column]
columns
  else
    [String] -> [Column] -> Table
Table [String]
table_names([Column] -> Table) -> [Column] -> Table
forall a b. (a -> b) -> a -> b
$ ([String] -> Column) -> [[String]] -> [Column]
forall a b. (a -> b) -> [a] -> [b]
map (\[String]
c_names -> [String] -> [Value] -> Column
Column [String]
c_names []) [[String]]
names

  where
    trans_data :: [[Value]]
trans_data = [[Value]] -> [[Value]]
forall a. [[a]] -> [[a]]
transpose ([[Value]] -> [[Value]]) -> [[Value]] -> [[Value]]
forall a b. (a -> b) -> a -> b
$ [[Value]]
in_data 

    n :: Int
n = [[Value]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Value]]
in_data
    m :: Int
m = [[Value]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Value]]
trans_data

    columns :: [Column]
    columns :: [Column]
columns = 
      let named_col_data :: [([String], [Value])]
named_col_data = [[String]] -> [[Value]] -> [([String], [Value])]
forall a b. [a] -> [b] -> [(a, b)]
zip [[String]]
names [[Value]]
trans_data in
      (([String], [Value]) -> Column)
-> [([String], [Value])] -> [Column]
forall a b. (a -> b) -> [a] -> [b]
map ([String], [Value]) -> Column
tieColumn [([String], [Value])]
named_col_data

      where
        tieColumn :: ([String], [Value]) -> Column
        tieColumn :: ([String], [Value]) -> Column
tieColumn ([String]
c_names, [Value]
vals) = [String] -> [Value] -> Column
Column [String]
c_names [Value]
vals

getRows :: [Column] -> [[Value]]
getRows :: [Column] -> [[Value]]
getRows [Column]
cols =
  [[Value]] -> [[Value]]
forall a. [[a]] -> [[a]]
transpose([[Value]] -> [[Value]]) -> [[Value]] -> [[Value]]
forall a b. (a -> b) -> a -> b
$ (Column -> [Value]) -> [Column] -> [[Value]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [Value]
columnValue [Column]
cols

-- | Cross joins two `Table`s into one.
crossJoinTable :: Table -> Table -> Table
crossJoinTable :: Table -> Table -> Table
crossJoinTable (Table [String]
names1 [Column]
cols1) (Table [String]
names2 [Column]
cols2) =
  [String] -> [[String]] -> [[Value]] -> Table
buildTable [String]
tableName [[String]]
colsNames([[Value]] -> Table) -> [[Value]] -> Table
forall a b. (a -> b) -> a -> b
$
    [[Value]
row1 [Value] -> [Value] -> [Value]
forall a. [a] -> [a] -> [a]
++ [Value]
row2 | [Value]
row1 <- [[Value]]
rows1, [Value]
row2 <- [[Value]]
rows2]

  where
    tableName :: [String]
    tableName :: [String]
tableName = [String]
names1 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
names2
   
    colsNames :: [[String]]
    colsNames :: [[String]]
colsNames = (Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
cols1 [[String]] -> [[String]] -> [[String]]
forall a. [a] -> [a] -> [a]
++ (Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
cols2

    rows1 :: [[Value]]
    rows1 :: [[Value]]
rows1 = [Column] -> [[Value]]
getRows [Column]
cols1

    rows2 :: [[Value]]
    rows2 :: [[Value]]
rows2 = [Column] -> [[Value]]
getRows [Column]
cols2


-- | Filters out rows, where the `Column` is `False`. 
-- The rows, where the `Column` is `True`, are kept.
filterTable :: Column -> Table -> Table
filterTable :: Column -> Table -> Table
filterTable (Column [String]
_ [Value]
if_cols) (Table [String]
t_name [Column]
cols) =
  [String] -> [[String]] -> [[Value]] -> Table
buildTable [String]
t_name [[String]]
cols_name([[Value]] -> Table) -> [[Value]] -> Table
forall a b. (a -> b) -> a -> b
$
    [Bool] -> [[Value]] -> [[Value]]
filterRows ((Value -> Bool) -> [Value] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Bool
forall a. Boolable a => a -> Bool
getBool [Value]
if_cols) [[Value]]
rows

  where
    rows :: [[Value]]
    rows :: [[Value]]
rows = [Column] -> [[Value]]
getRows [Column]
cols

    cols_name :: [[String]]
cols_name = (Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
cols

    filterRows :: [Bool] -> [[Value]] -> [[Value]]
    filterRows :: [Bool] -> [[Value]] -> [[Value]]
filterRows [] [] = []
    filterRows (Bool
False : [Bool]
r_bool) ([Value]
_ : [[Value]]
r_rows) = [Bool] -> [[Value]] -> [[Value]]
filterRows [Bool]
r_bool [[Value]]
r_rows
    filterRows (Bool
True : [Bool]
r_bool) ([Value]
row : [[Value]]
r_rows) = [Value]
row [Value] -> [[Value]] -> [[Value]]
forall a. a -> [a] -> [a]
: ([Bool] -> [[Value]] -> [[Value]]
filterRows [Bool]
r_bool [[Value]]
r_rows)

-- | Returns `Table` with same metadata as the original `Table`, but no data (no rows).
emptyTable :: Table -> Table
emptyTable :: Table -> Table
emptyTable (Table [String]
t_name [Column]
cols) = [String] -> [Column] -> Table
Table [String]
t_name 
  [[String] -> [Value] -> Column
Column (Column -> [String]
columnName Column
col) [] | Column
col <- [Column]
cols]


-- | Sorts a `Table` according to given `Column`s.
sortTable :: [Column] -> Table -> Table
sortTable :: [Column] -> Table -> Table
sortTable [] Table
table = Table
table

sortTable [Column]
s_cols (Table [String]
name [Column]
cols) =
  [String] -> [[String]] -> [[Value]] -> Table
buildTable [String]
name ((Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
cols)([[Value]] -> Table) -> [[Value]] -> Table
forall a b. (a -> b) -> a -> b
$
    [[Value]]
sorted_rows
  
  where
    s_rows :: [[Value]]
    s_rows :: [[Value]]
s_rows = [Column] -> [[Value]]
getRows [Column]
s_cols

    rows :: [[Value]]
    rows :: [[Value]]
rows = [Column] -> [[Value]]
getRows [Column]
cols

    sorted_p :: [([Value], [Value])]
    sorted_p :: [([Value], [Value])]
sorted_p = [([Value], [Value])] -> [([Value], [Value])]
forall a. Ord a => [a] -> [a]
sort([([Value], [Value])] -> [([Value], [Value])])
-> [([Value], [Value])] -> [([Value], [Value])]
forall a b. (a -> b) -> a -> b
$ [[Value]] -> [[Value]] -> [([Value], [Value])]
forall a b. [a] -> [b] -> [(a, b)]
zip [[Value]]
s_rows [[Value]]
rows

    sorted_rows :: [[Value]]
    sorted_rows :: [[Value]]
sorted_rows = (([Value], [Value]) -> [Value])
-> [([Value], [Value])] -> [[Value]]
forall a b. (a -> b) -> [a] -> [b]
map ([Value], [Value]) -> [Value]
forall a b. (a, b) -> b
snd [([Value], [Value])]
sorted_p


-- | Splits a `Table` into multiple `Table`s so that
-- rows of `Column`s at first argument are at each `Table` the same
-- and the number of `Table`s is minimal. (factorization)
byTable :: [Column] -> Table -> [Table]
byTable :: [Column] -> Table -> [Table]
byTable [Column]
s_cols Table
orig_table =
  ([[Value]] -> Table) -> [[[Value]]] -> [Table]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> [[String]] -> [[Value]] -> Table
buildTable [String]
name ((Column -> [String]) -> [Column] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map Column -> [String]
columnName [Column]
orig_cols))
    [[[Value]]]
new_rows

  where
    Table [String]
name [Column]
orig_cols = Table
orig_table

    s_rows :: [[Value]]
    s_rows :: [[Value]]
s_rows = [Column] -> [[Value]]
getRows [Column]
s_cols

    rows :: [[Value]]
    rows :: [[Value]]
rows = [Column] -> [[Value]]
getRows [Column]
orig_cols

    sorted_p :: [([Value], [Value])]
    sorted_p :: [([Value], [Value])]
sorted_p = [([Value], [Value])] -> [([Value], [Value])]
forall a. Ord a => [a] -> [a]
sort([([Value], [Value])] -> [([Value], [Value])])
-> [([Value], [Value])] -> [([Value], [Value])]
forall a b. (a -> b) -> a -> b
$ [[Value]] -> [[Value]] -> [([Value], [Value])]
forall a b. [a] -> [b] -> [(a, b)]
zip [[Value]]
s_rows [[Value]]
rows

    groupF :: ([Value], [Value]) -> ([Value], [Value]) -> Bool
    groupF :: ([Value], [Value]) -> ([Value], [Value]) -> Bool
groupF ([Value]
a, [Value]
_) ([Value]
b, [Value]
_) = [Value]
a [Value] -> [Value] -> Bool
forall a. Eq a => a -> a -> Bool
== [Value]
b

    grouped_p :: [[([Value], [Value])]]
    grouped_p :: [[([Value], [Value])]]
grouped_p = (([Value], [Value]) -> ([Value], [Value]) -> Bool)
-> [([Value], [Value])] -> [[([Value], [Value])]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy ([Value], [Value]) -> ([Value], [Value]) -> Bool
groupF [([Value], [Value])]
sorted_p

    new_rows :: [[[Value]]]
    new_rows :: [[[Value]]]
new_rows = ([([Value], [Value])] -> [[Value]])
-> [[([Value], [Value])]] -> [[[Value]]]
forall a b. (a -> b) -> [a] -> [b]
map ((([Value], [Value]) -> [Value])
-> [([Value], [Value])] -> [[Value]]
forall a b. (a -> b) -> [a] -> [b]
map ([Value], [Value]) -> [Value]
forall a b. (a, b) -> b
snd) [[([Value], [Value])]]
grouped_p