{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

module DataFrame.Monad (
    -- * The frame-state monad
    FrameM,
    runFrameM,
    evalFrameM,
    execFrameM,
    modifyM,
    inspectM,

    -- * Frame verbs
    deriveM,
    insertM,
    renameM,
    filterWhereM,
    sampleM,
    takeM,
    dropM,
    selectM,
    excludeM,
    sortByM,
    SortOrder (..),
    columnAsListM,
    filterJustM,
    imputeM,

    -- * Column-derivation pipelines
    Pipeline,
    letAs,
    letExpr,
    pipelineSteps,
    toFrameM,
    runPipeline,
) where

import Control.Monad (void)
import DataFrame.Internal.Column (Columnable)
import DataFrame.Internal.DataFrame (DataFrame)
import DataFrame.Internal.Expression (Expr (..), UExpr (..), prettyPrint)
import DataFrame.Internal.Nullable (BaseType)
import qualified DataFrame.Operations.Core as D
import DataFrame.Operations.Permutation (SortOrder)
import qualified DataFrame.Operations.Permutation as D
import qualified DataFrame.Operations.Subset as D
import DataFrame.Operations.Transformations (ImputeOp)
import qualified DataFrame.Operations.Transformations as D

import qualified Data.Text as T
import Data.Tuple (swap)
import System.Random

-- A re-implementation of the state monad.
-- `mtl` might be too heavy a dependency just to get
-- a single monad instance.
newtype FrameM a = FrameM {forall a. FrameM a -> DataFrame -> (DataFrame, a)
runFrameM_ :: DataFrame -> (DataFrame, a)}

instance Functor FrameM where
    fmap :: (a -> b) -> FrameM a -> FrameM b
    fmap :: forall a b. (a -> b) -> FrameM a -> FrameM b
fmap a -> b
f (FrameM DataFrame -> (DataFrame, a)
g) = (DataFrame -> (DataFrame, b)) -> FrameM b
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, b)) -> FrameM b)
-> (DataFrame -> (DataFrame, b)) -> FrameM b
forall a b. (a -> b) -> a -> b
$ \DataFrame
df ->
        let (DataFrame
df', a
x) = DataFrame -> (DataFrame, a)
g DataFrame
df
         in (DataFrame
df', a -> b
f a
x)

instance Applicative FrameM where
    pure :: forall a. a -> FrameM a
pure a
x = (DataFrame -> (DataFrame, a)) -> FrameM a
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM (,a
x)
    (<*>) :: FrameM (a -> b) -> FrameM a -> FrameM b
    FrameM DataFrame -> (DataFrame, a -> b)
ff <*> :: forall a b. FrameM (a -> b) -> FrameM a -> FrameM b
<*> FrameM DataFrame -> (DataFrame, a)
fx = (DataFrame -> (DataFrame, b)) -> FrameM b
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, b)) -> FrameM b)
-> (DataFrame -> (DataFrame, b)) -> FrameM b
forall a b. (a -> b) -> a -> b
$ \DataFrame
df ->
        let (DataFrame
df1, a -> b
f) = DataFrame -> (DataFrame, a -> b)
ff DataFrame
df
            (DataFrame
df2, a
x) = DataFrame -> (DataFrame, a)
fx DataFrame
df1
         in (DataFrame
df2, a -> b
f a
x)

instance Monad FrameM where
    (>>=) :: FrameM a -> (a -> FrameM b) -> FrameM b
    FrameM DataFrame -> (DataFrame, a)
g >>= :: forall a b. FrameM a -> (a -> FrameM b) -> FrameM b
>>= a -> FrameM b
f = (DataFrame -> (DataFrame, b)) -> FrameM b
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, b)) -> FrameM b)
-> (DataFrame -> (DataFrame, b)) -> FrameM b
forall a b. (a -> b) -> a -> b
$ \DataFrame
df ->
        let (DataFrame
df1, a
x) = DataFrame -> (DataFrame, a)
g DataFrame
df
            FrameM DataFrame -> (DataFrame, b)
h = a -> FrameM b
f a
x
         in DataFrame -> (DataFrame, b)
h DataFrame
df1

modifyM :: (DataFrame -> DataFrame) -> FrameM ()
modifyM :: (DataFrame -> DataFrame) -> FrameM ()
modifyM DataFrame -> DataFrame
f = (DataFrame -> (DataFrame, ())) -> FrameM ()
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, ())) -> FrameM ())
-> (DataFrame -> (DataFrame, ())) -> FrameM ()
forall a b. (a -> b) -> a -> b
$ \DataFrame
df -> (DataFrame -> DataFrame
f DataFrame
df, ())

inspectM :: (DataFrame -> b) -> FrameM b
inspectM :: forall b. (DataFrame -> b) -> FrameM b
inspectM DataFrame -> b
f = (DataFrame -> (DataFrame, b)) -> FrameM b
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, b)) -> FrameM b)
-> (DataFrame -> (DataFrame, b)) -> FrameM b
forall a b. (a -> b) -> a -> b
$ \DataFrame
df -> (DataFrame
df, DataFrame -> b
f DataFrame
df)

execWithExpr ::
    (Columnable a) => T.Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr :: forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
name DataFrame -> DataFrame
f = (DataFrame -> (DataFrame, Expr a)) -> FrameM (Expr a)
forall a. (DataFrame -> (DataFrame, a)) -> FrameM a
FrameM ((DataFrame -> (DataFrame, Expr a)) -> FrameM (Expr a))
-> (DataFrame -> (DataFrame, Expr a)) -> FrameM (Expr a)
forall a b. (a -> b) -> a -> b
$ \DataFrame
df ->
    let df' :: DataFrame
df' = DataFrame -> DataFrame
f DataFrame
df
     in (DataFrame
df', Text -> Expr a
forall a. Columnable a => Text -> Expr a
Col Text
name)

deriveM :: (Columnable a) => T.Text -> Expr a -> FrameM (Expr a)
deriveM :: forall a. Columnable a => Text -> Expr a -> FrameM (Expr a)
deriveM Text
name Expr a
expr = Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
name (Text -> Expr a -> DataFrame -> DataFrame
forall a. Columnable a => Text -> Expr a -> DataFrame -> DataFrame
D.derive Text
name Expr a
expr)

insertM :: (Columnable a) => T.Text -> [a] -> FrameM (Expr a)
insertM :: forall a. Columnable a => Text -> [a] -> FrameM (Expr a)
insertM Text
name [a]
values = Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
name (Text -> [a] -> DataFrame -> DataFrame
forall a (t :: * -> *).
(Columnable a, Foldable t) =>
Text -> t a -> DataFrame -> DataFrame
D.insert Text
name [a]
values)

renameM :: (Columnable a) => Expr a -> T.Text -> FrameM (Expr a)
renameM :: forall a. Columnable a => Expr a -> Text -> FrameM (Expr a)
renameM (Col Text
oldName) Text
newName = Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
newName (Text -> Text -> DataFrame -> DataFrame
D.rename Text
oldName Text
newName)
renameM Expr a
expr Text
newName = Text -> Expr a -> FrameM (Expr a)
forall a. Columnable a => Text -> Expr a -> FrameM (Expr a)
deriveM Text
newName Expr a
expr

filterWhereM :: Expr Bool -> FrameM ()
filterWhereM :: Expr Bool -> FrameM ()
filterWhereM Expr Bool
p = (DataFrame -> DataFrame) -> FrameM ()
modifyM (Expr Bool -> DataFrame -> DataFrame
D.filterWhere Expr Bool
p)

sampleM :: (RandomGen g) => g -> Double -> FrameM ()
sampleM :: forall g. RandomGen g => g -> Double -> FrameM ()
sampleM g
pureGen Double
p = (DataFrame -> DataFrame) -> FrameM ()
modifyM (g -> Double -> DataFrame -> DataFrame
forall g. RandomGen g => g -> Double -> DataFrame -> DataFrame
D.sample g
pureGen Double
p)

takeM :: Int -> FrameM ()
takeM :: Int -> FrameM ()
takeM Int
n = (DataFrame -> DataFrame) -> FrameM ()
modifyM (Int -> DataFrame -> DataFrame
D.take Int
n)

dropM :: Int -> FrameM ()
dropM :: Int -> FrameM ()
dropM Int
n = (DataFrame -> DataFrame) -> FrameM ()
modifyM (Int -> DataFrame -> DataFrame
D.drop Int
n)

-- | Keep only the named columns. 'dropM' drops rows; this drops columns.
selectM :: [T.Text] -> FrameM ()
selectM :: [Text] -> FrameM ()
selectM [Text]
names = (DataFrame -> DataFrame) -> FrameM ()
modifyM ([Text] -> DataFrame -> DataFrame
D.select [Text]
names)

-- | Drop the named columns.
excludeM :: [T.Text] -> FrameM ()
excludeM :: [Text] -> FrameM ()
excludeM [Text]
names = (DataFrame -> DataFrame) -> FrameM ()
modifyM ([Text] -> DataFrame -> DataFrame
D.exclude [Text]
names)

sortByM :: [SortOrder] -> FrameM ()
sortByM :: [SortOrder] -> FrameM ()
sortByM [SortOrder]
orders = (DataFrame -> DataFrame) -> FrameM ()
modifyM ([SortOrder] -> DataFrame -> DataFrame
D.sortBy [SortOrder]
orders)

columnAsListM :: (Columnable a) => Expr a -> FrameM [a]
columnAsListM :: forall a. Columnable a => Expr a -> FrameM [a]
columnAsListM Expr a
c = (DataFrame -> [a]) -> FrameM [a]
forall b. (DataFrame -> b) -> FrameM b
inspectM (Expr a -> DataFrame -> [a]
forall a. Columnable a => Expr a -> DataFrame -> [a]
D.columnAsList Expr a
c)

filterJustM :: (Columnable a) => Expr (Maybe a) -> FrameM (Expr a)
filterJustM :: forall a. Columnable a => Expr (Maybe a) -> FrameM (Expr a)
filterJustM (Col Text
name) = Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
name (Text -> DataFrame -> DataFrame
D.filterJust Text
name)
filterJustM Expr (Maybe a)
expr =
    [Char] -> FrameM (Expr a)
forall a. HasCallStack => [Char] -> a
error ([Char] -> FrameM (Expr a)) -> [Char] -> FrameM (Expr a)
forall a b. (a -> b) -> a -> b
$ [Char]
"Cannot filter on compound expression: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Expr (Maybe a) -> [Char]
forall a. Show a => a -> [Char]
show Expr (Maybe a)
expr

imputeM ::
    (ImputeOp a, Columnable (BaseType a)) =>
    Expr a ->
    BaseType a ->
    FrameM (Expr (BaseType a))
imputeM :: forall a.
(ImputeOp a, Columnable (BaseType a)) =>
Expr a -> BaseType a -> FrameM (Expr (BaseType a))
imputeM expr :: Expr a
expr@(Col Text
name) BaseType a
value = Text -> (DataFrame -> DataFrame) -> FrameM (Expr (BaseType a))
forall a.
Columnable a =>
Text -> (DataFrame -> DataFrame) -> FrameM (Expr a)
execWithExpr Text
name (Expr a -> BaseType a -> DataFrame -> DataFrame
forall a.
ImputeOp a =>
Expr a -> BaseType a -> DataFrame -> DataFrame
D.impute Expr a
expr BaseType a
value)
imputeM Expr a
expr BaseType a
_ = [Char] -> FrameM (Expr (BaseType a))
forall a. HasCallStack => [Char] -> a
error ([Char] -> FrameM (Expr (BaseType a)))
-> [Char] -> FrameM (Expr (BaseType a))
forall a b. (a -> b) -> a -> b
$ [Char]
"Cannot impute on compound expression: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Expr a -> [Char]
forall a. Show a => a -> [Char]
show Expr a
expr

runFrameM :: DataFrame -> FrameM a -> (a, DataFrame)
runFrameM :: forall a. DataFrame -> FrameM a -> (a, DataFrame)
runFrameM DataFrame
df (FrameM DataFrame -> (DataFrame, a)
action) = (DataFrame, a) -> (a, DataFrame)
forall a b. (a, b) -> (b, a)
swap (DataFrame -> (DataFrame, a)
action DataFrame
df)

evalFrameM :: DataFrame -> FrameM a -> a
evalFrameM :: forall a. DataFrame -> FrameM a -> a
evalFrameM DataFrame
df FrameM a
m = (a, DataFrame) -> a
forall a b. (a, b) -> a
fst (DataFrame -> FrameM a -> (a, DataFrame)
forall a. DataFrame -> FrameM a -> (a, DataFrame)
runFrameM DataFrame
df FrameM a
m)

execFrameM :: DataFrame -> FrameM a -> DataFrame
execFrameM :: forall a. DataFrame -> FrameM a -> DataFrame
execFrameM DataFrame
df FrameM a
m = (a, DataFrame) -> DataFrame
forall a b. (a, b) -> b
snd (DataFrame -> FrameM a -> (a, DataFrame)
forall a. DataFrame -> FrameM a -> (a, DataFrame)
runFrameM DataFrame
df FrameM a
m)

newtype Pipeline a = Pipeline {forall a. Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
unPipeline :: Int -> (Int, [(T.Text, UExpr)], a)}

instance Functor Pipeline where
    fmap :: forall a b. (a -> b) -> Pipeline a -> Pipeline b
fmap a -> b
f (Pipeline Int -> (Int, [(Text, UExpr)], a)
g) = (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline ((Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b)
-> (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a b. (a -> b) -> a -> b
$ \Int
n -> let (Int
n', [(Text, UExpr)]
w, a
a) = Int -> (Int, [(Text, UExpr)], a)
g Int
n in (Int
n', [(Text, UExpr)]
w, a -> b
f a
a)

instance Applicative Pipeline where
    pure :: forall a. a -> Pipeline a
pure a
x = (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline (,[],a
x)
    Pipeline Int -> (Int, [(Text, UExpr)], a -> b)
gf <*> :: forall a b. Pipeline (a -> b) -> Pipeline a -> Pipeline b
<*> Pipeline Int -> (Int, [(Text, UExpr)], a)
gx = (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline ((Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b)
-> (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a b. (a -> b) -> a -> b
$ \Int
n ->
        let (Int
n1, [(Text, UExpr)]
w1, a -> b
f) = Int -> (Int, [(Text, UExpr)], a -> b)
gf Int
n
            (Int
n2, [(Text, UExpr)]
w2, a
x) = Int -> (Int, [(Text, UExpr)], a)
gx Int
n1
         in (Int
n2, [(Text, UExpr)]
w1 [(Text, UExpr)] -> [(Text, UExpr)] -> [(Text, UExpr)]
forall a. [a] -> [a] -> [a]
++ [(Text, UExpr)]
w2, a -> b
f a
x)

instance Monad Pipeline where
    Pipeline Int -> (Int, [(Text, UExpr)], a)
g >>= :: forall a b. Pipeline a -> (a -> Pipeline b) -> Pipeline b
>>= a -> Pipeline b
f = (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline ((Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b)
-> (Int -> (Int, [(Text, UExpr)], b)) -> Pipeline b
forall a b. (a -> b) -> a -> b
$ \Int
n ->
        let (Int
n1, [(Text, UExpr)]
w1, a
a) = Int -> (Int, [(Text, UExpr)], a)
g Int
n
            (Int
n2, [(Text, UExpr)]
w2, b
b) = Pipeline b -> Int -> (Int, [(Text, UExpr)], b)
forall a. Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
unPipeline (a -> Pipeline b
f a
a) Int
n1
         in (Int
n2, [(Text, UExpr)]
w1 [(Text, UExpr)] -> [(Text, UExpr)] -> [(Text, UExpr)]
forall a. [a] -> [a] -> [a]
++ [(Text, UExpr)]
w2, b
b)

-- | Derive a column under an explicit name, returning a reference to it.
letAs :: (Columnable a) => T.Text -> Expr a -> Pipeline (Expr a)
letAs :: forall a. Columnable a => Text -> Expr a -> Pipeline (Expr a)
letAs Text
nm Expr a
e = (Int -> (Int, [(Text, UExpr)], Expr a)) -> Pipeline (Expr a)
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline (,[(Text
nm, Expr a -> UExpr
forall a. Columnable a => Expr a -> UExpr
UExpr Expr a
e)],Text -> Expr a
forall a. Columnable a => Text -> Expr a
Col Text
nm)

-- | Derive a column under a fresh generated name.
letExpr :: (Columnable a) => Expr a -> Pipeline (Expr a)
letExpr :: forall a. Columnable a => Expr a -> Pipeline (Expr a)
letExpr Expr a
e = (Int -> (Int, [(Text, UExpr)], Expr a)) -> Pipeline (Expr a)
forall a. (Int -> (Int, [(Text, UExpr)], a)) -> Pipeline a
Pipeline ((Int -> (Int, [(Text, UExpr)], Expr a)) -> Pipeline (Expr a))
-> (Int -> (Int, [(Text, UExpr)], Expr a)) -> Pipeline (Expr a)
forall a b. (a -> b) -> a -> b
$ \Int
n ->
    let nm :: Text
nm = [Char] -> Text
T.pack (Char
'_' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: Char
'v' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n) in (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, [(Text
nm, Expr a -> UExpr
forall a. Columnable a => Expr a -> UExpr
UExpr Expr a
e)], Text -> Expr a
forall a. Columnable a => Text -> Expr a
Col Text
nm)

instance Show (Pipeline (Expr a)) where
    show :: Pipeline (Expr a) -> [Char]
show Pipeline (Expr a)
p =
        let (Int
_, [(Text, UExpr)]
steps, Expr a
res) = Pipeline (Expr a) -> Int -> (Int, [(Text, UExpr)], Expr a)
forall a. Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
unPipeline Pipeline (Expr a)
p Int
0
         in ((Text, UExpr) -> [Char]) -> [(Text, UExpr)] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap
                (\(Text
nm, UExpr Expr a
e) -> Text -> [Char]
T.unpack Text
nm [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" = " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Expr a -> [Char]
forall a. Expr a -> [Char]
prettyPrint Expr a
e [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n")
                [(Text, UExpr)]
steps
                [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"return "
                [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Expr a -> [Char]
forall a. Expr a -> [Char]
prettyPrint Expr a
res

-- | Number of column derivations the pipeline performs.
pipelineSteps :: Pipeline a -> Int
pipelineSteps :: forall a. Pipeline a -> Int
pipelineSteps Pipeline a
p = let (Int
_, [(Text, UExpr)]
w, a
_) = Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
forall a. Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
unPipeline Pipeline a
p Int
0 in [(Text, UExpr)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Text, UExpr)]
w

-- | Interpret a pipeline into 'FrameM', deriving each logged column in order.
toFrameM :: Pipeline (Expr a) -> FrameM (Expr a)
toFrameM :: forall a. Pipeline (Expr a) -> FrameM (Expr a)
toFrameM Pipeline (Expr a)
p =
    let (Int
_, [(Text, UExpr)]
steps, Expr a
res) = Pipeline (Expr a) -> Int -> (Int, [(Text, UExpr)], Expr a)
forall a. Pipeline a -> Int -> (Int, [(Text, UExpr)], a)
unPipeline Pipeline (Expr a)
p Int
0
     in ((Text, UExpr) -> FrameM ()) -> [(Text, UExpr)] -> FrameM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\(Text
nm, UExpr Expr a
e) -> FrameM (Expr a) -> FrameM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Text -> Expr a -> FrameM (Expr a)
forall a. Columnable a => Text -> Expr a -> FrameM (Expr a)
deriveM Text
nm Expr a
e)) [(Text, UExpr)]
steps FrameM () -> FrameM (Expr a) -> FrameM (Expr a)
forall a b. FrameM a -> FrameM b -> FrameM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Expr a -> FrameM (Expr a)
forall a. a -> FrameM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Expr a
res

{- | Run a pipeline over a frame: derive its columns and return the result
expression (a reference to the final column) and the resulting frame.
-}
runPipeline :: DataFrame -> Pipeline (Expr a) -> (Expr a, DataFrame)
runPipeline :: forall a. DataFrame -> Pipeline (Expr a) -> (Expr a, DataFrame)
runPipeline DataFrame
df = DataFrame -> FrameM (Expr a) -> (Expr a, DataFrame)
forall a. DataFrame -> FrameM a -> (a, DataFrame)
runFrameM DataFrame
df (FrameM (Expr a) -> (Expr a, DataFrame))
-> (Pipeline (Expr a) -> FrameM (Expr a))
-> Pipeline (Expr a)
-> (Expr a, DataFrame)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pipeline (Expr a) -> FrameM (Expr a)
forall a. Pipeline (Expr a) -> FrameM (Expr a)
toFrameM