packages feed

Frames 0.7.2 → 0.7.3

raw patch · 12 files changed

+41/−37 lines, 12 filesdep +http-client-tlsdep ~basedep ~ghc-primdep ~vinylPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: http-client-tls

Dependency ranges changed: base, ghc-prim, vinyl

API changes (from Hackage documentation)

- Frames: data ElField (field :: (Symbol, Type))
+ Frames: data ElField (t :: (Symbol, Type))
- Frames.Exploration: recToList :: forall a (rs :: [(Symbol, *)]). (RecMapMethod ((~) a) ElField rs, RecordToList rs) => Record rs -> [a]
+ Frames.Exploration: recToList :: forall a (rs :: [(Symbol, Type)]). (RecMapMethod ((~) a) ElField rs, RecordToList rs) => Record rs -> [a]
- Frames.RecF: class ColumnHeaders (cs :: [(Symbol, *)])
+ Frames.RecF: class ColumnHeaders (cs :: [(Symbol, Type)])

Files

Frames.cabal view
@@ -1,5 +1,5 @@ name:                Frames-version:             0.7.2+version:             0.7.3 synopsis:            Data frames For working with tabular data files description:         User-friendly, type safe, runtime efficient tooling for                      working with tabular data deserialized from@@ -30,7 +30,7 @@                      data/left1.csv data/right1.csv data/left_summary.csv                      data/FL2.csv cabal-version:       >=1.10-tested-with:         GHC == 8.6.5 || == 8.8.4 || == 8.10.4 || == 9.0.1+tested-with:         GHC == 8.6.5 || == 8.8.4 || == 8.10.7 || == 9.0.1 || == 9.2.1  source-repository head   type:     git@@ -64,8 +64,8 @@                        TypeOperators, ConstraintKinds, StandaloneDeriving,                        UndecidableInstances, ScopedTypeVariables,                        OverloadedStrings, TypeApplications-  build-depends:       base >=4.10 && <4.16,-                       ghc-prim >=0.3 && <0.8,+  build-depends:       base >=4.10 && <4.17,+                       ghc-prim >=0.3 && <0.9,                        primitive >= 0.6 && < 0.8,                        text >= 1.1.1.0,                        template-haskell,@@ -78,7 +78,7 @@                        pipes-parse >= 3.0 && < 3.1,                        pipes-safe >= 2.2.6 && < 2.4,                        bytestring,-                       vinyl >= 0.13.0 && < 0.14,+                       vinyl >= 0.13.0 && < 0.15,                        discrimination,                        contravariant,                        hashable,@@ -95,7 +95,11 @@     buildable: False   main-is: GetData.hs   if flag(demos)-    build-depends: base, bytestring, http-client >= 0.4.3, zip-archive, directory+    build-depends:+      base, bytestring,+      http-client >= 0.4.3,+      http-client-tls,+      zip-archive, directory   hs-source-dirs: data   default-language: Haskell2010   ghc-options: -Wall@@ -146,7 +150,7 @@                    pipes   hs-source-dirs: demo/framestack/app   default-language: Haskell2010-  ghc-options: -O2+  ghc-options: -O2 -fsimpl-tick-factor=200   -- ghc-options: -O2 -fllvm  executable tutorial@@ -172,7 +176,7 @@   hs-source-dirs:   benchmarks   default-language: Haskell2010   -- ghc-options:      -O2-  ghc-options: -O2 -fllvm+  ghc-options: -O2 -fllvm -fsimpl-tick-factor=200  -- A demonstration of dealing with missing data. Provided for source -- code and experimentation rather than a useful executable.@@ -234,7 +238,7 @@                        temporary, directory, htoml, regex-applicative, pretty,                        unordered-containers, pipes, HUnit, vinyl,                        foldl >= 1.3 && < 1.5,-                       attoparsec, lens+                       attoparsec, lens, bytestring   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall   default-language:    Haskell2010 
README.md view
@@ -17,7 +17,7 @@  If you have a CSV data where the values of each column may be classified by a single type, and ideally you have a header row giving each column a name, you may simply want to avoid writing out the Haskell type corresponding to each row. `Frames` provides `TemplateHaskell` machinery to infer a Haskell type for each row of your data set, thus preventing the situation where your code quietly diverges from your data. -We generate a collection of definitions generated by inspecting the data file at compile time (using `tableTypes`), then, at runtime, load that data into column-oriented storage in memory (an **in-core** array of structures (AoS)). We're going to compute the average ratio of two columns, so we'll use the `foldl` library. Our fold will project the columns we want, and apply a function that divides one by the other after appropriate numeric type conversions. Here is the entirety of that [program](https://github.com/acowley/Frames/tree/master/test/UncurryFold.hs).+We generate a collection of definitions generated by inspecting the data file at compile time (using `tableTypes`), then, at runtime, load that data into column-oriented storage in memory with a row-oriented interface (an **in-core** array of structures (AoS)). We're going to compute the average ratio of two columns, so we'll use the `foldl` library. Our fold will project the columns we want, and apply a function that divides one by the other after appropriate numeric type conversions. Here is the entirety of that [program](https://github.com/acowley/Frames/tree/master/test/UncurryFold.hs).  ```haskell {-# LANGUAGE DataKinds, FlexibleContexts, QuasiQuotes, TemplateHaskell, TypeApplications #-}
data/GetData.hs view
@@ -4,13 +4,14 @@ import Data.Maybe (fromJust) import Data.Monoid (First(..)) import Network.HTTP.Client+import Network.HTTP.Client.TLS (tlsManagerSettings) import System.Directory (createDirectoryIfMissing)  getPrestige :: IO ()-getPrestige = do m <- newManager defaultManagerSettings+getPrestige = do m <- newManager tlsManagerSettings                  httpLbs req m >>=                    B.writeFile "data/prestige.csv" . responseBody-  where Just req = parseUrlThrow "http://vincentarelbundock.github.io/Rdatasets/csv/car/Prestige.csv"+  where Just req = parseUrlThrow "https://vincentarelbundock.github.io/Rdatasets/csv/carData/Prestige.csv"  getFLinsurance :: IO () getFLinsurance = do m <- newManager defaultManagerSettings
demo/Plot2.hs view
@@ -44,6 +44,7 @@           putStrLn $ "The average farmer/fisher is "++                      show (fromIntegral age_ / n) ++                      " and made " ++ show (fromIntegral inc / n)+          mkPlot   where aux !(!sumAge, !sumIncome, n) f = (sumAge + f^.age, sumIncome + f^.capitalGain, n+1)  -- Independent folds
src/Frames/CSV.hs view
@@ -244,7 +244,6 @@                   -> P.Producer (Rec (Maybe :. ElField) rs) m () readTableMaybeOpt opts csvFile =   produceTokens csvFile (columnSeparator opts) >-> pipeTableMaybeOpt opts-{-# INLINE readTableMaybeOpt #-}  -- | Stream lines of CSV data into rows of ’Rec’ values values where -- any given entry can fail to parse.@@ -256,7 +255,6 @@   P.map (rmap (either (const (Compose Nothing))                       (Compose . Just) . getCompose)          . readRec)-{-# INLINE pipeTableMaybeOpt #-}  -- | Stream lines of CSV data into rows of ’Rec’ values values where -- any given entry can fail to parse. In the case of a parse failure, the@@ -267,20 +265,17 @@ pipeTableEitherOpt opts = do   when (isNothing (headerOverride opts)) (() <$ P.await)   P.map (readRow opts)-{-# INLINE pipeTableEitherOpt #-}  -- | Produce rows where any given entry can fail to parse. readTableMaybe :: (P.MonadSafe m, ReadRec rs, RMap rs)                => FilePath -> P.Producer (Rec (Maybe :. ElField) rs) m () readTableMaybe = readTableMaybeOpt defaultParser-{-# INLINE readTableMaybe #-}  -- | Stream lines of CSV data into rows of ’Rec’ values where any -- given entry can fail to parse. pipeTableMaybe :: (Monad m, ReadRec rs, RMap rs)                => P.Pipe [T.Text] (Rec (Maybe :. ElField) rs) m () pipeTableMaybe = pipeTableMaybeOpt defaultParser-{-# INLINE pipeTableMaybe #-}  -- | Stream lines of CSV data into rows of ’Rec’ values where any -- given entry can fail to parse. In the case of a parse failure, the@@ -288,7 +283,6 @@ pipeTableEither :: (Monad m, ReadRec rs)                 => P.Pipe T.Text (Rec (Either T.Text :. ElField) rs) m () pipeTableEither = pipeTableEitherOpt defaultParser-{-# INLINE pipeTableEither #-}  -- -- | Returns a `MonadPlus` producer of rows for which each column was -- -- successfully parsed. This is typically slower than 'readTableOpt'.@@ -305,14 +299,12 @@ --               False -> let r = recMaybe . readRow opts <$> T.hGetLine h --                        in liftIO r >>= maybe go (flip mplus go . return) --      go--- {-# INLINE readTableOpt' #-}  -- -- | Returns a `MonadPlus` producer of rows for which each column was -- -- successfully parsed. This is typically slower than 'readTable'. -- readTable' :: forall m rs. (P.MonadSafe m, ReadRec rs) --            => FilePath -> m (Record rs) -- readTable' = readTableOpt' defaultParser--- {-# INLINE readTable' #-}  -- | Returns a producer of rows for which each column was successfully -- parsed.@@ -320,21 +312,18 @@              => ParserOptions -> FilePath -> P.Producer (Record rs) m () readTableOpt opts csvFile = readTableMaybeOpt opts csvFile P.>-> go   where go = P.await >>= maybe go (\x -> P.yield x >> go) . recMaybe-{-# INLINE readTableOpt #-}  -- | Pipe lines of CSV text into rows for which each column was -- successfully parsed. pipeTableOpt :: (ReadRec rs, RMap rs, Monad m)              => ParserOptions -> P.Pipe [T.Text] (Record rs) m () pipeTableOpt opts = pipeTableMaybeOpt opts >-> P.map recMaybe >-> P.concat-{-# INLINE pipeTableOpt #-}  -- | Returns a producer of rows for which each column was successfully -- parsed. readTable :: (P.MonadSafe m, ReadRec rs, RMap rs)           => FilePath -> P.Producer (Record rs) m () readTable = readTableOpt defaultParser-{-# INLINE readTable #-}  readRecEither :: (ReadRec rs, RMap rs)               => [T.Text] -> Either (Rec (Either T.Text :. ElField) rs) (Record rs)@@ -372,7 +361,6 @@ pipeTable :: (ReadRec rs, RMap rs, Monad m)           => P.Pipe [T.Text] (Record rs) m () pipeTable = pipeTableOpt defaultParser-{-# INLINE pipeTable #-}  -- * Writing CSV Data 
src/Frames/Categorical.hs view
@@ -76,7 +76,11 @@         fromStringClause variant variantCon =           Clause [LitP (StringL variant)] (NormalB (ConE variantCon)) []         showCSVClause variant variantCon =+#if MIN_VERSION_template_haskell(2,18,0)+          Clause [ConP variantCon [] []]+#else           Clause [ConP variantCon []]+#endif                  (NormalB (AppE (VarE 'T.pack) (LitE (StringL variant))))                  []         readableGuarded :: Name -> String -> Name -> (Guard, Exp)
src/Frames/ColumnUniverse.hs view
@@ -98,7 +98,6 @@  instance (T.Text ∈ ts, RPureConstrained Parseable ts) => Monoid (CoRec ColInfo ts) where   mempty = CoRec (ColInfo ( Right (ConT (mkName "Text")), Possibly T.empty))-  mappend x y = x <> y  -- | A helper For the 'Semigroup' instance below. mergeEqTypeParses :: forall ts. (RPureConstrained Parseable ts, T.Text ∈ ts)
src/Frames/Exploration.hs view
@@ -14,6 +14,7 @@                            takeRows, dropRows) where import Data.Char (isSpace, isUpper) import qualified Data.Foldable as F+import Data.Kind (Type) import Data.List (intercalate) import Data.Proxy import qualified Data.Vinyl as V@@ -21,7 +22,7 @@ import Data.Vinyl.Functor (ElField(Field), Const(..)) import Frames.Rec import GHC.TypeLits (Symbol)-import Language.Haskell.TH+import Language.Haskell.TH hiding (Type) import Language.Haskell.TH.Quote import Pipes hiding (Proxy) import qualified Pipes as P@@ -92,7 +93,7 @@  -- * ToList -recToList :: forall a (rs :: [(Symbol,*)]).+recToList :: forall a (rs :: [(Symbol, Type)]).              (V.RecMapMethod ((~) a) ElField rs, V.RecordToList rs)           => Record rs -> [a] recToList = V.recordToList . V.rmapMethod @((~) a) aux
src/Frames/Frame.hs view
@@ -36,7 +36,6 @@ -- a new 'Frame' with the rows of @f1@ followed by the rows of @f2@. instance Monoid (Frame r) where   mempty = Frame 0 (const $ error "index out of bounds (empty frame)")-  f1 `mappend` f2 = f1 <> f2  instance Semigroup (Frame r) where   Frame l1 f1 <> Frame l2 f2 =
src/Frames/InCore.hs view
@@ -1,11 +1,12 @@ {-# LANGUAGE BangPatterns, CPP, DataKinds, EmptyCase,-             FlexibleInstances, PolyKinds, ScopedTypeVariables,-             TupleSections, TypeFamilies, TypeOperators,-             UndecidableInstances #-}+             FlexibleContexts, FlexibleInstances, PolyKinds,+             ScopedTypeVariables, TupleSections, TypeFamilies,+             TypeOperators, UndecidableInstances #-} -- | Efficient in-memory (in-core) storage of tabular data. module Frames.InCore where import Control.Monad.Primitive import Control.Monad.ST (runST)+import Data.Kind (Type) import Data.Proxy import Data.Text (Text) import qualified Data.Vector as VB@@ -23,12 +24,12 @@ import GHC.Prim (RealWorld) #endif import GHC.TypeLits (KnownSymbol)-import GHC.Types (Symbol, Type)+import GHC.Types (Symbol) import qualified Pipes as P import qualified Pipes.Prelude as P  -- | The most efficient vector type for each column data type.-type family VectorFor t :: * -> *+type family VectorFor t :: Type -> Type type instance VectorFor Bool = VU.Vector type instance VectorFor Int = VU.Vector type instance VectorFor Float = VU.Vector
src/Frames/RecF.hs view
@@ -29,6 +29,7 @@                     ColFun, ColumnHeaders,                     columnHeaders) where -- import Data.List (intercalate)+import Data.Kind (Type) import Data.Proxy import qualified Data.Vinyl as V import Data.Vinyl (Rec(..))@@ -70,7 +71,7 @@ -- pattern x :& xs <- (frameUncons -> (x, xs)) where --   x :& xs = frameCons x xs -class ColumnHeaders (cs::[(Symbol,*)]) where+class ColumnHeaders (cs::[(Symbol, Type)]) where   -- | Return the column names for a record.   columnHeaders :: proxy (Rec f cs) -> [String] @@ -88,7 +89,7 @@  -- | Strip the column information from each element of a list of -- types.-type family UnColumn (ts :: [(Symbol,*)]) where+type family UnColumn (ts :: [(Symbol, Type)]) where   UnColumn '[] = '[]   UnColumn ((s :-> t) ': ts) = t ': UnColumn ts 
test/DataCSV.hs view
@@ -2,10 +2,12 @@ module DataCSV where import Control.Monad ((>=>)) import Data.Bifunctor (first)+import qualified Data.ByteString as BS import qualified Data.HashMap.Lazy as H import Data.Maybe (catMaybes) import qualified Data.Text as T import qualified Data.Text.IO as T+import Data.Text.Encoding (decodeUtf8) import Language.Haskell.TH.Syntax (Lift(..)) import Text.Toml import Text.Toml.Types (Node (VTable, VString), Table)@@ -20,8 +22,11 @@ --   lift (CsvExample n c g) = [e| CsvExample n c g |]  examplesFrom :: FilePath -> IO [CsvExample]-examplesFrom fp = (either error id . ((first show . parseTomlDoc "examples") >=> go))-                <$> T.readFile fp+examplesFrom fp =+  (either error id+   . ((first show . parseTomlDoc "examples") >=> go)+   . decodeUtf8)+  <$> BS.readFile fp   where go :: Table -> Either String [CsvExample]         go = fmap catMaybes . mapM (uncurry ex . first T.unpack) . H.toList         ex :: String -> Node -> Either String (Maybe CsvExample)