content: {-# LANGUAGE TemplateHaskell   #-}
  {-# LANGUAGE DataKinds         #-}
  {-# LANGUAGE FlexibleContexts  #-}
  {-# LANGUAGE TypeOperators     #-}
  {-# LANGUAGE OverloadedLabels #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE RankNTypes        #-}
  {-# LANGUAGE TypeApplications  #-}
  module Issue114 where
  import           Frames
  import qualified Control.Foldl                 as Foldl
  import           Control.Lens
  import           Pipes.Prelude                  ( fold )
  import           Pipes
  import qualified Pipes.Prelude                 as P
  import qualified Pipes.Core                    as PC
  
  import qualified Data.Vinyl                    as V
  import           Data.Vinyl                     ( Rec(..) )
  
  import qualified Data.Text                     as T
  import           Data.Attoparsec.Text
  import           Control.Applicative
  
  import           Frames.TH                      ( tableTypesText'
                                                  , rowGen
                                                  , RowGen(..)
                                                  )
  
  tableTypesText' (rowGen "test/data/issue114.csv") { rowTypeName = "ProductionData" }
  
  declareColumn "oil_vol_double" ''Double
  
  getOilVol :: ProductionData -> Record '[OilVolDouble]
  getOilVol x = V.Field (f (parseOnly parseDouble (x ^. oilVol))) :& RNil
   where
    f (Left  _) = 0.0 / 0.0
    f (Right y) = y
  
  readOilVol :: MonadSafe m => Producer (Record '[OilVolDouble]) m ()
  readOilVol = (readTable "test/data/issue114.csv") >-> (P.map getOilVol)
  
  oilVolLength :: Foldl.Fold (Record '[OilVolDouble]) Int
  oilVolLength = Foldl.length
  
  totalOilVol :: Foldl.Fold (Record '[OilVolDouble]) Double
  totalOilVol = (Foldl.handles oilVolDouble) Foldl.sum
  
  oilVolTotalAndLength :: Foldl.Fold (Record '[OilVolDouble]) (Double, Int)
  oilVolTotalAndLength = (,) <$> totalOilVol <*> oilVolLength
  
  parseDouble :: Parser Double
  parseDouble =
    do
        d <- double
        return d
      <|> do
            _ <- string ""
            return 0.0
  
  test :: IO ()
  test = do
    (t, l) <- runSafeT $ Foldl.purely fold oilVolTotalAndLength readOilVol
    putStrLn $ show l ++ " records totalling " ++ show t
  
  loadTable :: MonadSafe m => PC.Producer ProductionData m ()
  loadTable = readTable "test/data/issue114.csv"
  
  testNames :: IO [T.Text]
  testNames = runSafeT . P.toListM $ loadTable >-> P.map (V.rvalf #facility_name)
  