{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

module DataFrame.Internal.Expression where

import Data.String
import qualified Data.Text as T
import Data.Type.Equality (TestEquality (testEquality), type (:~:) (Refl))
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Unboxed as VU
import DataFrame.Internal.Column
import Type.Reflection (Typeable, typeOf, typeRep)

data Expr a where
    Col :: (Columnable a) => T.Text -> Expr a
    Lit :: (Columnable a) => a -> Expr a
    UnaryOp ::
        (Columnable a, Columnable b) => T.Text -> (b -> a) -> Expr b -> Expr a
    BinaryOp ::
        (Columnable c, Columnable b, Columnable a) =>
        T.Text -> (c -> b -> a) -> Expr c -> Expr b -> Expr a
    If :: (Columnable a) => Expr Bool -> Expr a -> Expr a -> Expr a
    AggVector ::
        (VG.Vector v b, Typeable v, Columnable a, Columnable b) =>
        Expr b -> T.Text -> (v b -> a) -> Expr a
    AggReduce :: (Columnable a) => Expr a -> T.Text -> (a -> a -> a) -> Expr a
    -- TODO(mchav): Numeric reduce might be superfluous since expressions are already type checked.
    AggNumericVector ::
        (Columnable a, Columnable b, VU.Unbox a, VU.Unbox b, Num a, Num b) =>
        Expr b -> T.Text -> (VU.Vector b -> a) -> Expr a
    AggFold ::
        forall a b.
        (Columnable a, Columnable b) => Expr b -> T.Text -> a -> (a -> b -> a) -> Expr a

data UExpr where
    Wrap :: (Columnable a) => Expr a -> UExpr

instance Show UExpr where
    show :: UExpr -> String
    show :: UExpr -> String
show (Wrap Expr a
expr) = Expr a -> String
forall a. Show a => a -> String
show Expr a
expr

type NamedExpr = (T.Text, UExpr)

instance (Num a, Columnable a) => Num (Expr a) where
    (+) :: Expr a -> Expr a -> Expr a
    + :: Expr a -> Expr a -> Expr a
(+) (Lit a
x) (Lit a
y) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
y)
    (+) Expr a
e1 Expr a
e2
        | Expr a
e1 Expr a -> Expr a -> Bool
forall a. Eq a => a -> a -> Bool
== Expr a
e2 = Text -> (a -> a -> a) -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
"mult" a -> a -> a
forall a. Num a => a -> a -> a
(*) Expr a
e1 (a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
2)
        | Bool
otherwise = Text -> (a -> a -> a) -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
"add" a -> a -> a
forall a. Num a => a -> a -> a
(+) Expr a
e1 Expr a
e2

    (-) :: Expr a -> Expr a -> Expr a
    (-) (Lit a
x) (Lit a
y) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
y)
    (-) Expr a
e1 Expr a
e2 = Text -> (a -> a -> a) -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
"sub" (-) Expr a
e1 Expr a
e2

    (*) :: Expr a -> Expr a -> Expr a
    * :: Expr a -> Expr a -> Expr a
(*) (Lit a
0) Expr a
_ = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
0
    (*) Expr a
_ (Lit a
0) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
0
    (*) (Lit a
1) Expr a
e = Expr a
e
    (*) Expr a
e (Lit a
1) = Expr a
e
    (*) (Lit a
x) (Lit a
y) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
y)
    (*) Expr a
e1 Expr a
e2
        | Expr a
e1 Expr a -> Expr a -> Bool
forall a. Eq a => a -> a -> Bool
== Expr a
e2 = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"pow 2" (a -> Integer -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) Expr a
e1
        | Bool
otherwise = Text -> (a -> a -> a) -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
"mult" a -> a -> a
forall a. Num a => a -> a -> a
(*) Expr a
e1 Expr a
e2

    fromInteger :: Integer -> Expr a
    fromInteger :: Integer -> Expr a
fromInteger = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> Expr a) -> (Integer -> a) -> Integer -> Expr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. Num a => Integer -> a
fromInteger

    negate :: Expr a -> Expr a
    negate :: Expr a -> Expr a
negate (Lit a
n) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> a
forall a. Num a => a -> a
negate a
n)
    negate Expr a
expr = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"negate" a -> a
forall a. Num a => a -> a
negate Expr a
expr

    abs :: (Num a) => Expr a -> Expr a
    abs :: Num a => Expr a -> Expr a
abs (Lit a
n) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> a
forall a. Num a => a -> a
abs a
n)
    abs Expr a
expr = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"abs" a -> a
forall a. Num a => a -> a
abs Expr a
expr

    signum :: (Num a) => Expr a -> Expr a
    signum :: Num a => Expr a -> Expr a
signum (Lit a
n) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> a
forall a. Num a => a -> a
signum a
n)
    signum Expr a
expr = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"signum" a -> a
forall a. Num a => a -> a
signum Expr a
expr

add :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
add :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
add = Expr a -> Expr a -> Expr a
forall a. Num a => a -> a -> a
(+)

sub :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
sub :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
sub = (-)

mult :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
mult :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
mult = Expr a -> Expr a -> Expr a
forall a. Num a => a -> a -> a
(*)

instance (Fractional a, Columnable a) => Fractional (Expr a) where
    fromRational :: (Fractional a, Columnable a) => Rational -> Expr a
    fromRational :: (Fractional a, Columnable a) => Rational -> Expr a
fromRational = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> Expr a) -> (Rational -> a) -> Rational -> Expr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> a
forall a. Fractional a => Rational -> a
fromRational

    (/) :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
    / :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
(/) (Lit a
l1) (Lit a
l2) = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a
l1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
l2)
    (/) Expr a
e1 Expr a
e2 = Text -> (a -> a -> a) -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
"divide" a -> a -> a
forall a. Fractional a => a -> a -> a
(/) Expr a
e1 Expr a
e2

divide :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
divide :: forall a.
(Fractional a, Columnable a) =>
Expr a -> Expr a -> Expr a
divide = Expr a -> Expr a -> Expr a
forall a. Fractional a => a -> a -> a
(/)

instance (IsString a, Columnable a) => IsString (Expr a) where
    fromString :: String -> Expr a
    fromString :: String -> Expr a
fromString String
s = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (String -> a
forall a. IsString a => String -> a
fromString String
s)

instance (Floating a, Columnable a) => Floating (Expr a) where
    pi :: (Floating a, Columnable a) => Expr a
    pi :: (Floating a, Columnable a) => Expr a
pi = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
forall a. Floating a => a
pi
    exp :: (Floating a, Columnable a) => Expr a -> Expr a
    exp :: (Floating a, Columnable a) => Expr a -> Expr a
exp = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"exp" a -> a
forall a. Floating a => a -> a
exp
    log :: (Floating a, Columnable a) => Expr a -> Expr a
    log :: (Floating a, Columnable a) => Expr a -> Expr a
log = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"log" a -> a
forall a. Floating a => a -> a
log
    sin :: (Floating a, Columnable a) => Expr a -> Expr a
    sin :: (Floating a, Columnable a) => Expr a -> Expr a
sin = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"sin" a -> a
forall a. Floating a => a -> a
sin
    cos :: (Floating a, Columnable a) => Expr a -> Expr a
    cos :: (Floating a, Columnable a) => Expr a -> Expr a
cos = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"cos" a -> a
forall a. Floating a => a -> a
cos
    asin :: (Floating a, Columnable a) => Expr a -> Expr a
    asin :: (Floating a, Columnable a) => Expr a -> Expr a
asin = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"asin" a -> a
forall a. Floating a => a -> a
asin
    acos :: (Floating a, Columnable a) => Expr a -> Expr a
    acos :: (Floating a, Columnable a) => Expr a -> Expr a
acos = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"acos" a -> a
forall a. Floating a => a -> a
acos
    atan :: (Floating a, Columnable a) => Expr a -> Expr a
    atan :: (Floating a, Columnable a) => Expr a -> Expr a
atan = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"atan" a -> a
forall a. Floating a => a -> a
atan
    sinh :: (Floating a, Columnable a) => Expr a -> Expr a
    sinh :: (Floating a, Columnable a) => Expr a -> Expr a
sinh = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"sinh" a -> a
forall a. Floating a => a -> a
sinh
    cosh :: (Floating a, Columnable a) => Expr a -> Expr a
    cosh :: (Floating a, Columnable a) => Expr a -> Expr a
cosh = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"cosh" a -> a
forall a. Floating a => a -> a
cosh
    asinh :: (Floating a, Columnable a) => Expr a -> Expr a
    asinh :: (Floating a, Columnable a) => Expr a -> Expr a
asinh = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"asinh" a -> a
forall a. Floating a => a -> a
sinh
    acosh :: (Floating a, Columnable a) => Expr a -> Expr a
    acosh :: (Floating a, Columnable a) => Expr a -> Expr a
acosh = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"acosh" a -> a
forall a. Floating a => a -> a
acosh
    atanh :: (Floating a, Columnable a) => Expr a -> Expr a
    atanh :: (Floating a, Columnable a) => Expr a -> Expr a
atanh = Text -> (a -> a) -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
"atanh" a -> a
forall a. Floating a => a -> a
atanh

instance (Show a) => Show (Expr a) where
    show :: forall a. (Show a) => Expr a -> String
    show :: forall a. Show a => Expr a -> String
show (Col Text
name) = String
"(col @" String -> ShowS
forall a. [a] -> [a] -> [a]
++ TypeRep a -> String
forall a. Show a => a -> String
show (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Lit a
value) = String
"(lit (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
value String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"))"
    show (If Expr Bool
cond Expr a
l Expr a
r) = String
"(ifThenElse " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr Bool -> String
forall a. Show a => a -> String
show Expr Bool
cond String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Show a => a -> String
show Expr a
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Show a => a -> String
show Expr a
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (UnaryOp Text
name b -> a
f Expr b
value) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
value String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (BinaryOp Text
name c -> b -> a
f Expr c
a Expr b
b) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr c -> String
forall a. Show a => a -> String
show Expr c
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
b String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (AggNumericVector Expr b
expr Text
op Vector b -> a
_) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (AggVector Expr b
expr Text
op v b -> a
_) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (AggReduce Expr a
expr Text
op a -> a -> a
_) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Show a => a -> String
show Expr a
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (AggFold Expr b
expr Text
op a
_ a -> b -> a
_) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

normalize :: (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize :: forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
expr = case Expr a
expr of
    Col Text
name -> Text -> Expr a
forall a. Columnable a => Text -> Expr a
Col Text
name
    Lit a
val -> a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
val
    If Expr Bool
cond Expr a
th Expr a
el -> Expr Bool -> Expr a -> Expr a -> Expr a
forall a. Columnable a => Expr Bool -> Expr a -> Expr a -> Expr a
If (Expr Bool -> Expr Bool
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr Bool
cond) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
th) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
el)
    UnaryOp Text
name b -> a
f Expr b
e -> Text -> (b -> a) -> Expr b -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
name b -> a
f (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e)
    BinaryOp Text
name c -> b -> a
f Expr c
e1 Expr b
e2
        | Text -> Bool
isCommutative Text
name ->
            let n1 :: Expr c
n1 = Expr c -> Expr c
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr c
e1
                n2 :: Expr b
n2 = Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e2
             in case TypeRep (Expr c) -> TypeRep (Expr b) -> Maybe (Expr c :~: Expr b)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
n1) (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
n2) of
                    Maybe (Expr c :~: Expr b)
Nothing -> Expr a
expr
                    Just Expr c :~: Expr b
Refl ->
                        if Expr c -> Expr c -> Ordering
forall a. Expr a -> Expr a -> Ordering
compareExpr Expr c
n1 Expr c
Expr b
n2 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
GT
                            then Text -> (c -> b -> a) -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
name c -> b -> a
f Expr c
Expr b
n2 Expr c
Expr b
n1 -- Swap to canonical order
                            else Text -> (c -> b -> a) -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
name c -> b -> a
f Expr c
n1 Expr b
n2
        | Bool
otherwise -> Text -> (c -> b -> a) -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
name c -> b -> a
f (Expr c -> Expr c
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr c
e1) (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e2)
    AggVector Expr b
e Text
name v b -> a
f -> Expr b -> Text -> (v b -> a) -> Expr a
forall (b :: * -> *) b a.
(Vector b b, Typeable b, Columnable a, Columnable b) =>
Expr b -> Text -> (b b -> a) -> Expr a
AggVector (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e) Text
name v b -> a
f
    AggReduce Expr a
e Text
name a -> a -> a
f -> Expr a -> Text -> (a -> a -> a) -> Expr a
forall a. Columnable a => Expr a -> Text -> (a -> a -> a) -> Expr a
AggReduce (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
e) Text
name a -> a -> a
f
    AggNumericVector Expr b
e Text
name Vector b -> a
f -> Expr b -> Text -> (Vector b -> a) -> Expr a
forall a b.
(Columnable a, Columnable b, Unbox a, Unbox b, Num a, Num b) =>
Expr b -> Text -> (Vector b -> a) -> Expr a
AggNumericVector (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e) Text
name Vector b -> a
f
    AggFold Expr b
e Text
name a
init a -> b -> a
f -> Expr b -> Text -> a -> (a -> b -> a) -> Expr a
forall a b.
(Columnable a, Columnable b) =>
Expr b -> Text -> a -> (a -> b -> a) -> Expr a
AggFold (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e) Text
name a
init a -> b -> a
f

isCommutative :: T.Text -> Bool
isCommutative :: Text -> Bool
isCommutative Text
name =
    Text
name
        Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Text
"add"
               , Text
"mult"
               , Text
"min"
               , Text
"max"
               , Text
"eq"
               , Text
"and"
               , Text
"or"
               ]

-- Compare expressions for ordering (used in normalization)
compareExpr :: Expr a -> Expr a -> Ordering
compareExpr :: forall a. Expr a -> Expr a -> Ordering
compareExpr Expr a
e1 Expr a
e2 = String -> String -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e1) (Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e2)
  where
    exprKey :: Expr a -> String
    exprKey :: forall a. Expr a -> String
exprKey (Col Text
name) = String
"0:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name
    exprKey (Lit a
val) = String
"1:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
val
    exprKey (If Expr Bool
c Expr a
t Expr a
e) = String
"2:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr Bool -> String
forall a. Expr a -> String
exprKey Expr Bool
c String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Expr a -> String
exprKey Expr a
t String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e
    exprKey (UnaryOp Text
name b -> a
_ Expr b
e) = String
"3:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (BinaryOp Text
name c -> b -> a
_ Expr c
e1 Expr b
e2) = String
"4:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr c -> String
forall a. Expr a -> String
exprKey Expr c
e1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e2
    exprKey (AggVector Expr b
e Text
name v b -> a
_) = String
"5:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (AggReduce Expr a
e Text
name a -> a -> a
_) = String
"6:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e
    exprKey (AggNumericVector Expr b
e Text
name Vector b -> a
_) = String
"7:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (AggFold Expr b
e Text
name a
_ a -> b -> a
_) = String
"8:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e

instance (Eq a, Columnable a) => Eq (Expr a) where
    == :: Expr a -> Expr a -> Bool
(==) Expr a
l Expr a
r = Expr a -> Expr a -> Bool
eqNormalized (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
l) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
r)
      where
        exprEq :: (Columnable b, Columnable c) => Expr b -> Expr c -> Bool
        exprEq :: forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
exprEq Expr b
e1 Expr c
e2 = case TypeRep (Expr b) -> TypeRep (Expr c) -> Maybe (Expr b :~: Expr c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
e1) (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
e2) of
            Just Expr b :~: Expr c
Refl -> Expr b
e1 Expr b -> Expr b -> Bool
forall a. Eq a => a -> a -> Bool
== Expr b
Expr c
e2
            Maybe (Expr b :~: Expr c)
Nothing -> Bool
False
        eqNormalized :: Expr a -> Expr a -> Bool
        eqNormalized :: Expr a -> Expr a -> Bool
eqNormalized (Col Text
n1) (Col Text
n2) = Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2
        eqNormalized (Lit a
v1) (Lit a
v2) = a
v1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
v2
        eqNormalized (If Expr Bool
c1 Expr a
t1 Expr a
e1) (If Expr Bool
c2 Expr a
t2 Expr a
e2) =
            Expr Bool
c1 Expr Bool -> Expr Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Expr Bool
c2 Bool -> Bool -> Bool
&& Expr a
t1 Expr a -> Expr a -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr a
t2 Bool -> Bool -> Bool
&& Expr a
e1 Expr a -> Expr a -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr a
e2
        eqNormalized (UnaryOp Text
n1 b -> a
_ Expr b
e1) (UnaryOp Text
n2 b -> a
_ Expr b
e2) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (BinaryOp Text
n1 c -> b -> a
_ Expr c
e1a Expr b
e1b) (BinaryOp Text
n2 c -> b -> a
_ Expr c
e2a Expr b
e2b) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr c
e1a Expr c -> Expr c -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr c
e2a Bool -> Bool -> Bool
&& Expr b
e1b Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2b
        eqNormalized (AggVector Expr b
e1 Text
n1 v b -> a
_) (AggVector Expr b
e2 Text
n2 v b -> a
_) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (AggReduce Expr a
e1 Text
n1 a -> a -> a
_) (AggReduce Expr a
e2 Text
n2 a -> a -> a
_) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr a
e1 Expr a -> Expr a -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr a
e2
        eqNormalized (AggNumericVector Expr b
e1 Text
n1 Vector b -> a
_) (AggNumericVector Expr b
e2 Text
n2 Vector b -> a
_) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (AggFold Expr b
e1 Text
n1 a
i1 a -> b -> a
_) (AggFold Expr b
e2 Text
n2 a
i2 a -> b -> a
_) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2 Bool -> Bool -> Bool
&& a
i1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
i2
        eqNormalized Expr a
_ Expr a
_ = Bool
False

instance (Ord a, Columnable a) => Ord (Expr a) where
    compare :: Expr a -> Expr a -> Ordering
    compare :: Expr a -> Expr a -> Ordering
compare Expr a
e1 Expr a
e2 = case (Expr a
e1, Expr a
e2) of
        (Col Text
n1, Col Text
n2) -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2
        (Lit a
v1, Lit a
v2) -> a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
v1 a
v2
        (If Expr Bool
c1 Expr a
t1 Expr a
e1', If Expr Bool
c2 Expr a
t2 Expr a
e2') ->
            Expr Bool -> Expr Bool -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Expr Bool
c1 Expr Bool
c2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr a -> Expr a -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr a
t1 Expr a
t2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr a -> Expr a -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr a
e1' Expr a
e2'
        (UnaryOp Text
n1 b -> a
_ Expr b
e1', UnaryOp Text
n2 b -> a
_ Expr b
e2') ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (BinaryOp Text
n1 c -> b -> a
_ Expr c
a1 Expr b
b1, BinaryOp Text
n2 c -> b -> a
_ Expr c
a2 Expr b
b2) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr c -> Expr c -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr c
a1 Expr c
a2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
b1 Expr b
b2
        (AggVector Expr b
e1' Text
n1 v b -> a
_, AggVector Expr b
e2' Text
n2 v b -> a
_) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (AggReduce Expr a
e1' Text
n1 a -> a -> a
_, AggReduce Expr a
e2' Text
n2 a -> a -> a
_) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr a -> Expr a -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr a
e1' Expr a
e2'
        (AggNumericVector Expr b
e1' Text
n1 Vector b -> a
_, AggNumericVector Expr b
e2' Text
n2 Vector b -> a
_) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (AggFold Expr b
e1' Text
n1 a
i1 a -> b -> a
_, AggFold Expr b
e2' Text
n2 a
i2 a -> b -> a
_) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2' Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
i1 a
i2
        -- Different constructors - compare by priority
        (Col Text
_, Expr a
_) -> Ordering
LT
        (Expr a
_, Col Text
_) -> Ordering
GT
        (Lit a
_, Expr a
_) -> Ordering
LT
        (Expr a
_, Lit a
_) -> Ordering
GT
        (UnaryOp{}, Expr a
_) -> Ordering
LT
        (Expr a
_, UnaryOp{}) -> Ordering
GT
        (BinaryOp{}, Expr a
_) -> Ordering
LT
        (Expr a
_, BinaryOp{}) -> Ordering
GT
        (If{}, Expr a
_) -> Ordering
LT
        (Expr a
_, If{}) -> Ordering
GT
        (AggVector{}, Expr a
_) -> Ordering
LT
        (Expr a
_, AggVector{}) -> Ordering
GT
        (AggReduce{}, Expr a
_) -> Ordering
LT
        (Expr a
_, AggReduce{}) -> Ordering
GT
        (AggNumericVector{}, Expr a
_) -> Ordering
LT
        (Expr a
_, AggNumericVector{}) -> Ordering
GT

exprComp :: (Columnable b, Columnable c) => Expr b -> Expr c -> Ordering
exprComp :: forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1 Expr c
e2 = case TypeRep (Expr b) -> TypeRep (Expr c) -> Maybe (Expr b :~: Expr c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
e1) (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
e2) of
    Just Expr b :~: Expr c
Refl -> Expr b
e1 Expr b -> Expr b -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Expr b
Expr c
e2
    Maybe (Expr b :~: Expr c)
Nothing -> Ordering
LT

replaceExpr ::
    forall a b c.
    (Columnable a, Columnable b, Columnable c) =>
    Expr a -> Expr b -> Expr c -> Expr c
replaceExpr :: forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
expr = case TypeRep b -> TypeRep c -> Maybe (b :~: c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @c) of
    Just b :~: c
Refl -> case TypeRep a -> TypeRep c -> Maybe (a :~: c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @c) of
        Just a :~: c
Refl -> if Expr b
old Expr b -> Expr b -> Bool
forall a. Eq a => a -> a -> Bool
== Expr b
Expr c
expr then Expr a
Expr c
new else Expr c
replace'
        Maybe (a :~: c)
Nothing -> Expr c
expr
    Maybe (b :~: c)
Nothing -> Expr c
replace'
  where
    replace' :: Expr c
replace' = case Expr c
expr of
        (Col Text
_) -> Expr c
expr
        (Lit c
_) -> Expr c
expr
        (If Expr Bool
cond Expr c
l Expr c
r) ->
            Expr Bool -> Expr c -> Expr c -> Expr c
forall a. Columnable a => Expr Bool -> Expr a -> Expr a -> Expr a
If (Expr a -> Expr b -> Expr Bool -> Expr Bool
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr Bool
cond) (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
l) (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
r)
        (UnaryOp Text
name b -> c
f Expr b
value) -> Text -> (b -> c) -> Expr b -> Expr c
forall a b.
(Columnable a, Columnable b) =>
Text -> (b -> a) -> Expr b -> Expr a
UnaryOp Text
name b -> c
f (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
value)
        (BinaryOp Text
name c -> b -> c
f Expr c
l Expr b
r) -> Text -> (c -> b -> c) -> Expr c -> Expr b -> Expr c
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
Text -> (b -> b -> a) -> Expr b -> Expr b -> Expr a
BinaryOp Text
name c -> b -> c
f (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
l) (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
r)
        (AggNumericVector Expr b
expr Text
op Vector b -> c
f) -> Expr b -> Text -> (Vector b -> c) -> Expr c
forall a b.
(Columnable a, Columnable b, Unbox a, Unbox b, Num a, Num b) =>
Expr b -> Text -> (Vector b -> a) -> Expr a
AggNumericVector (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
expr) Text
op Vector b -> c
f
        (AggVector Expr b
expr Text
op v b -> c
f) -> Expr b -> Text -> (v b -> c) -> Expr c
forall (b :: * -> *) b a.
(Vector b b, Typeable b, Columnable a, Columnable b) =>
Expr b -> Text -> (b b -> a) -> Expr a
AggVector (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
expr) Text
op v b -> c
f
        (AggReduce Expr c
expr Text
op c -> c -> c
f) -> Expr c -> Text -> (c -> c -> c) -> Expr c
forall a. Columnable a => Expr a -> Text -> (a -> a -> a) -> Expr a
AggReduce (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
expr) Text
op c -> c -> c
f
        (AggFold Expr b
expr Text
op c
acc c -> b -> c
f) -> Expr b -> Text -> c -> (c -> b -> c) -> Expr c
forall a b.
(Columnable a, Columnable b) =>
Expr b -> Text -> a -> (a -> b -> a) -> Expr a
AggFold (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
expr) Text
op c
acc c -> b -> c
f

eSize :: Expr a -> Int
eSize :: forall a. Expr a -> Int
eSize (Col Text
_) = Int
1
eSize (Lit a
_) = Int
1
eSize (If Expr Bool
c Expr a
l Expr a
r) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr Bool -> Int
forall a. Expr a -> Int
eSize Expr Bool
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr a -> Int
forall a. Expr a -> Int
eSize Expr a
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr a -> Int
forall a. Expr a -> Int
eSize Expr a
r
eSize (UnaryOp Text
_ b -> a
_ Expr b
e) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
e
eSize (BinaryOp Text
_ c -> b -> a
_ Expr c
l Expr b
r) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr c -> Int
forall a. Expr a -> Int
eSize Expr c
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
r
eSize (AggNumericVector Expr b
expr Text
op Vector b -> a
_) = Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
expr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
eSize (AggVector Expr b
expr Text
op v b -> a
_) = Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
expr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
eSize (AggReduce Expr a
expr Text
op a -> a -> a
_) = Expr a -> Int
forall a. Expr a -> Int
eSize Expr a
expr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
eSize (AggFold Expr b
expr Text
op a
_ a -> b -> a
_) = Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
expr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1