{-# LANGUAGE FlexibleContexts #-}

{- |
Module      : DataFrame.TH.CSV
License     : MIT

CSV-file-based 'DataFrame.TH' splices. Splits out the CSV ingest path so
@dataframe-th@ stays IO-agnostic.
-}
module DataFrame.TH.CSV (
    declareColumnsFromCsvFile,
    declareColumnsFromCsvWithOpts,
) where

import Control.Monad.IO.Class (liftIO)
import Language.Haskell.TH

import qualified DataFrame.IO.CSV as CSV
import DataFrame.TH.Records (declareColumns)

{- | Splice a binding for every column of the 'DataFrame' read from a CSV
file. Each binding has type @Expr T@ where @T@ is the inferred column
type.
-}
declareColumnsFromCsvFile :: String -> DecsQ
declareColumnsFromCsvFile :: String -> DecsQ
declareColumnsFromCsvFile String
path = do
    DataFrame
df <-
        IO DataFrame -> Q DataFrame
forall a. IO a -> Q a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
            ( ReadOptions -> String -> IO DataFrame
CSV.readSeparated
                (ReadOptions
CSV.defaultReadOptions{CSV.numRowsToRead = Just 100})
                String
path
            )
    DataFrame -> DecsQ
declareColumns DataFrame
df

-- | Like 'declareColumnsFromCsvFile' but with custom 'CSV.ReadOptions'.
declareColumnsFromCsvWithOpts :: CSV.ReadOptions -> String -> DecsQ
declareColumnsFromCsvWithOpts :: ReadOptions -> String -> DecsQ
declareColumnsFromCsvWithOpts ReadOptions
opts String
path = do
    DataFrame
df <- IO DataFrame -> Q DataFrame
forall a. IO a -> Q a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (ReadOptions -> String -> IO DataFrame
CSV.readSeparated ReadOptions
opts String
path)
    DataFrame -> DecsQ
declareColumns DataFrame
df