-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Data frames For working with tabular data files -- -- User-friendly, type safe, runtime efficient tooling for working with -- tabular data deserialized from comma-separated values (CSV) files. The -- type of each row of data is inferred from data, which can then be -- streamed from disk, or worked with in memory. @package Frames @version 0.6.2 -- | Column types module Frames.Col type (a :: Symbol) :-> b = '(a, b) pattern Col :: KnownSymbol s => t -> ElField '(s, t) -- | Get the data payload of a named field. getCol :: ElField '(s, t) -> t -- | Used only for a show instance that parenthesizes the value. newtype Col' s a Col' :: ElField (s :-> a) -> Col' s a -- | Helper for making a Col' col' :: KnownSymbol s => a -> Col' s a -- | ReplaceColumns x ys keeps the textual name of each element of -- ys, but replaces its data type with x. type family ReplaceColumns x ys instance (GHC.TypeLits.KnownSymbol s, GHC.Show.Show a) => GHC.Show.Show (Frames.Col.Col' s a) module Frames.ColumnTypeable data Parsed a Possibly :: a -> Parsed a Definitely :: a -> Parsed a parsedValue :: Parsed a -> a -- | Values that can be read from a Text with more or less -- discrimination. class Parseable a -- | Returns Nothing if a value of the given type can not be read; -- returns 'Just Possibly' if a value can be read, but is likely -- ambiguous (e.g. an empty string); returns 'Just Definitely' if a value -- can be read and is unlikely to be ambiguous." parse :: (Parseable a, MonadPlus m) => Text -> m (Parsed a) -- | Returns Nothing if a value of the given type can not be read; -- returns 'Just Possibly' if a value can be read, but is likely -- ambiguous (e.g. an empty string); returns 'Just Definitely' if a value -- can be read and is unlikely to be ambiguous." parse :: (Parseable a, Readable a, MonadPlus m) => Text -> m (Parsed a) -- | Combine two parse results such that the combination can fail. Useful -- when we have two Possibly parsed values that are different -- enough to suggest the parse of each should be considered a failure. -- The default implementation is to return the first argument. parseCombine :: (Parseable a, MonadPlus m) => Parsed a -> Parsed a -> m (Parsed a) -- | Combine two parse results such that the combination can fail. Useful -- when we have two Possibly parsed values that are different -- enough to suggest the parse of each should be considered a failure. -- The default implementation is to return the first argument. parseCombine :: (Parseable a, MonadPlus m) => Parsed a -> Parsed a -> m (Parsed a) representableAsType :: Parseable a => Parsed a -> Const (Either (String -> Q [Dec]) Type) a representableAsType :: (Parseable a, Typeable a) => Parsed a -> Const (Either (String -> Q [Dec]) Type) a -- | Discard any estimate of a parse's ambiguity. discardConfidence :: Parsed a -> a -- | Acts just like fromText: tries to parse a value from a -- Text and discards any estimate of the parse's ambiguity. parse' :: (MonadPlus m, Parseable a) => Text -> m a parseIntish :: (Readable a, MonadPlus f) => Text -> f (Parsed a) -- | This class relates a universe of possible column types to Haskell -- types, and provides a mechanism to infer which type best represents -- some textual data. class ColumnTypeable a colType :: ColumnTypeable a => a -> Either (String -> Q [Dec]) Type inferType :: ColumnTypeable a => Text -> a instance GHC.Show.Show a => GHC.Show.Show (Frames.ColumnTypeable.Parsed a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Frames.ColumnTypeable.Parsed a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Frames.ColumnTypeable.Parsed a) instance Frames.ColumnTypeable.Parseable GHC.Types.Bool instance Frames.ColumnTypeable.Parseable GHC.Types.Int instance Frames.ColumnTypeable.Parseable GHC.Int.Int32 instance Frames.ColumnTypeable.Parseable GHC.Int.Int64 instance Frames.ColumnTypeable.Parseable GHC.Integer.Type.Integer instance Frames.ColumnTypeable.Parseable GHC.Types.Float instance Frames.ColumnTypeable.Parseable GHC.Types.Double instance Frames.ColumnTypeable.Parseable Data.Text.Internal.Text instance GHC.Base.Functor Frames.ColumnTypeable.Parsed module Frames.Rec -- | A record with unadorned values. This is Vinyl's Rec -- ElField. We give this type a name as it is used pervasively for -- records in Frames. type Record = FieldRec -- | A cons function for building Record values. (&:) :: KnownSymbol s => a -> Record rs -> Record ((s :-> a) : rs) infixr 5 &: type family RecordColumns t -- | Separate the first element of a Record from the rest of the -- row. recUncons :: Record ((s :-> a) : rs) -> (a, Record rs) -- | Undistribute Maybe from a Rec Maybe. This is just -- a specific usage of rtraverse, but it is quite common. recMaybe :: Rec (Maybe :. ElField) cs -> Maybe (Record cs) -- | Show each field of a Record without its column name. showFields :: (RecMapMethod Show ElField ts, RecordToList ts) => Record ts -> [String] -- | Get the value of a field of a Record. This is intended for use -- with TypeApplications, as compared to rgetv that is -- intended for use with OverloadedLabels. rgetField :: forall t s a rs. (t ~ '(s, a), t ∈ rs) => Record rs -> a -- | Replace the value of a field of a Record. This is intended for -- use with TypeApplications, as compared to rputf that -- is intended for use with OverloadedLabels. rputField :: forall t s a rs. (t ~ '(s, a), t ∈ rs, KnownSymbol s) => a -> Record rs -> Record rs -- | Functions useful for interactively exploring and experimenting with a -- data set. module Frames.Exploration -- | preview src n f prints out the first n results of -- piping src through f. pipePreview :: (Show b, MonadIO m, MonadMask m) => Producer a (SafeT m) () -> Int -> Pipe a b (SafeT m) () -> m () -- | select (Proxy::Proxy [A,B,C]) extracts columns A, -- B, and C, from a larger record. Note, this is just a -- way of pinning down the type of a usage of rcast. -- | Deprecated: Use Data.Vinyl.rcast with a type application. select :: fs ⊆ rs => proxy fs -> Record rs -> Record fs -- | lenses (Proxy::Proxy [A,B,C]) provides a lens onto columns -- A, B, and C. This is just a way of pinning -- down the type of rsubset. -- | Deprecated: Use Data.Vinyl.rsubset with a type application. lenses :: (fs ⊆ rs, Functor f) => proxy fs -> (Record fs -> f (Record fs)) -> Record rs -> f (Record rs) recToList :: forall a (rs :: [(Symbol, *)]). (RecMapMethod ((~) a) ElField rs, RecordToList rs) => Record rs -> [a] -- | A proxy value quasiquoter; a way of passing types as values. -- [pr|T|] will splice an expression Proxy::Proxy T, -- while [pr|A,B,C|] will splice in a value of Proxy :: -- Proxy [A,B,C]. If we have a record type with Name and -- Age among other fields, we can write select -- [pr|Name,Age|]@ for a function that extracts those fields from a -- larger record. pr :: QuasiQuoter -- | Like pr, but takes a single type, which is used to produce a -- Proxy for a single-element list containing only that type. This -- is useful for passing a single type to a function that wants a list of -- types. pr1 :: QuasiQuoter module Frames.ShowCSV -- | Control the way values of a type are printed when serializing to a CSV -- stream. class ShowCSV a showCSV :: ShowCSV a => a -> Text showCSV :: (ShowCSV a, Show a) => a -> Text instance Frames.ShowCSV.ShowCSV GHC.Types.Bool instance Frames.ShowCSV.ShowCSV GHC.Types.Int instance Frames.ShowCSV.ShowCSV GHC.Types.Double instance Frames.ShowCSV.ShowCSV Data.Text.Internal.Text -- | Helpers for working with type-level lists. module Frames.TypeLevel -- | Constraint that every element of a promoted list is equal to a -- particular type. That is, the list of types is a single type repeated -- some number of times. type family AllAre a ts :: Constraint -- | ReplaceAll x ys produces a type-level list of the same length -- as ys where each element is x. In other words, it -- replaces each element of ys with x. This would be -- map (const x) ys in value-level Haskell. type family ReplaceAll a xs -- | Replace the second component of every tuple in a type-level list with -- a constant. type family ReplaceAllSnd a (xs :: [(k1, k2)]) module Frames.RecF -- | Two records may be pasted together. rappend :: () => Rec f as -> Rec f bs -> Rec f (as ++ bs) -- | A record may be traversed with respect to its interpretation functor. -- This can be used to yank (some or all) effects from the fields of the -- record to the outside of the record. rtraverse :: Applicative h => (forall (x :: u). () => f x -> h (g x)) -> Rec f rs -> h (Rec g rs) -- | Delete a field from a record rdel :: CanDelete r rs => Rec f rs -> Rec f (RDelete r rs) -- | A constraint that a field can be deleted from a record. type CanDelete r rs = (RElem r rs (RIndex r rs), RDelete r rs ⊆ rs) -- | Enforce a constraint on the payload type of each column. type AllCols c ts = AllConstrained c (UnColumn ts) -- | Strip the column information from each element of a list of types. type family UnColumn (ts :: [(Symbol, *)]) -- | Facilities for removing and replacing the type-level label, or column -- name, part of a record. class StripFieldNames (ts :: [(Symbol, Type)]) stripNames :: StripFieldNames ts => Rec ElField ts -> Rec Identity (Unlabeled ts) stripNames' :: (StripFieldNames ts, Functor f) => Rec (f :. ElField) ts -> Rec f (Unlabeled ts) withNames :: StripFieldNames ts => Rec Identity (Unlabeled ts) -> Rec ElField ts withNames' :: (StripFieldNames ts, Functor f) => Rec f (Unlabeled ts) -> Rec (f :. ElField) ts -- | Map a function across a homogeneous Rec of named values. This -- is a thin wrapper over mapMonoV. mapMono :: (AllAre a (Unlabeled ts), StripFieldNames ts, StripFieldNames (ReplaceAllSnd b ts), ReplaceAll b (Unlabeled ts) ~ Unlabeled (ReplaceAllSnd b ts)) => (a -> b) -> Rec ElField ts -> Rec ElField (ReplaceAllSnd b ts) -- | A type function to convert a 'Rec f' to a 'Rec (g :. f)'. ColFun f -- (Record rs) = Rec (f :. ElField) rs. type family ColFun f x class ColumnHeaders (cs :: [(Symbol, *)]) -- | Return the column names for a record. columnHeaders :: ColumnHeaders cs => proxy (Rec f cs) -> [String] instance Frames.RecF.ColumnHeaders '[] instance (Frames.RecF.ColumnHeaders cs, GHC.TypeLits.KnownSymbol s) => Frames.RecF.ColumnHeaders ((s Frames.Col.:-> c) : cs) -- | A Frame is a finite Int-indexed collection of rows. module Frames.Frame -- | A Frame is a finite collection of rows indexed by Int. data Frame r Frame :: !Int -> (Int -> r) -> Frame r [frameLength] :: Frame r -> !Int [frameRow] :: Frame r -> Int -> r -- | A Frame whose rows are Record values. type FrameRec rs = Frame (Record rs) -- | Build a Frame from any Foldable. This simply uses a -- boxed Vector to hold each row. If you have a collection of -- Records, consider using toFrame. boxedFrame :: Foldable f => f r -> Frame r -- | Horizontal Frame concatenation. That is, zipFrames f1 -- f2 will return a Frame with as many rows as the smaller of -- f1 and f2 whose rows are the result of appending the -- columns of f2 to those of f1. zipFrames :: FrameRec rs -> FrameRec rs' -> FrameRec (rs ++ rs') instance GHC.Base.Functor Frames.Frame.Frame instance GHC.Classes.Eq r => GHC.Classes.Eq (Frames.Frame.Frame r) instance GHC.Base.Monoid (Frames.Frame.Frame r) instance GHC.Base.Semigroup (Frames.Frame.Frame r) instance Data.Foldable.Foldable Frames.Frame.Frame instance GHC.Base.Applicative Frames.Frame.Frame instance GHC.Base.Monad Frames.Frame.Frame module Frames.Melt type family Elem t ts :: Bool type family Or (a :: Bool) (b :: Bool) :: Bool type family Not a :: Bool type family Disjoint ss ts :: Bool type ElemOf ts r = RElem r ts (RIndex r ts) class RowToColumn ts rs rowToColumnAux :: RowToColumn ts rs => Proxy ts -> Rec f rs -> [CoRec f ts] -- | Transform a record into a list of its fields, retaining proof that -- each field is part of the whole. rowToColumn :: RowToColumn ts ts => Rec f ts -> [CoRec f ts] meltAux :: forall vs ss ts. (vs ⊆ ts, ss ⊆ ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)] type family RDeleteAll ss ts -- | This is melt, but the variables are at the front of the record, -- which reads a bit odd. meltRow' :: forall proxy vs ts ss. (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => proxy ss -> Record ts -> [Record (("value" :-> CoRec ElField vs) : ss)] -- | Turn a cons into a snoc after the fact. retroSnoc :: forall t ts. Record (t : ts) -> Record (ts ++ '[t]) -- | Like melt in the reshape2 package for the R -- language. It stacks multiple columns into a single column over -- multiple rows. Takes a specification of the id columns that remain -- unchanged. The remaining columns will be stacked. -- -- Suppose we have a record, r :: Record [Name,Age,Weight]. If -- we apply melt [pr1|Name|] r, we get two values with type -- Record [Name, "value" :-> CoRec Identity [Age,Weight]]. -- The first will contain Age in the value column, and -- the second will contain Weight in the value column. meltRow :: (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => proxy ss -> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])] class HasLength (ts :: [k]) hasLength :: HasLength ts => proxy ts -> Int -- | Applies meltRow to each row of a FrameRec. melt :: forall vs ts ss proxy. (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, HasLength vs, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => proxy ss -> FrameRec ts -> FrameRec (ss ++ '["value" :-> CoRec ElField vs]) instance Frames.Melt.HasLength '[] instance forall k (t :: k) (ts :: [k]). Frames.Melt.HasLength ts => Frames.Melt.HasLength (t : ts) instance forall k (ts :: [k]). Frames.Melt.RowToColumn ts '[] instance forall a (r :: a) (ts :: [a]) (rs :: [a]). (r Data.Vinyl.Lens.∈ ts, Frames.Melt.RowToColumn ts rs) => Frames.Melt.RowToColumn ts (r : rs) -- | Efficient in-memory (in-core) storage of tabular data. module Frames.InCore -- | The most efficient vector type for each column data type. type family VectorFor t :: * -> * -- | The mutable version of VectorFor a particular type. type VectorMFor a = Mutable (VectorFor a) -- | Since we stream into the in-memory representation, we use an -- exponential growth strategy to resize arrays as more data is read in. -- This is the initial capacity of each column. initialCapacity :: Int -- | Mutable vector types for each column in a row. type family VectorMs m rs -- | Immutable vector types for each column in a row. type family Vectors rs -- | Tooling to allocate, grow, write to, freeze, and index into records of -- vectors. class RecVec (rs :: [(Symbol, Type)]) allocRec :: (RecVec rs, PrimMonad m) => proxy rs -> Int -> m (Record (VectorMs m rs)) freezeRec :: (RecVec rs, PrimMonad m) => proxy rs -> Int -> Record (VectorMs m rs) -> m (Record (Vectors rs)) growRec :: (RecVec rs, PrimMonad m) => proxy rs -> Record (VectorMs m rs) -> m (Record (VectorMs m rs)) writeRec :: (RecVec rs, PrimMonad m) => proxy rs -> Int -> Record (VectorMs m rs) -> Record rs -> m () indexRec :: RecVec rs => proxy rs -> Int -> Record (Vectors rs) -> Record rs produceRec :: RecVec rs => proxy rs -> Record (Vectors rs) -> Rec ((->) Int :. ElField) rs -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generators a matter of indexing into a densely packed -- representation. Returns the number of rows and a record of column -- indexing functions. See toAoS to convert the result to a -- Frame which provides an easier-to-use function that indexes -- into the table in a row-major fashion. inCoreSoA :: forall m rs. (PrimMonad m, RecVec rs) => Producer (Record rs) m () -> m (Int, Rec ((->) Int :. ElField) rs) -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generators a matter of indexing into a densely packed -- representation. Returns a Frame that provides a function to -- index into the table. inCoreAoS :: (PrimMonad m, RecVec rs) => Producer (Record rs) m () -> m (FrameRec rs) -- | Like inCoreAoS, but applies the provided function to the record -- of columns before building the Frame. inCoreAoS' :: (PrimMonad m, RecVec rs) => (Rec ((->) Int :. ElField) rs -> Rec ((->) Int :. ElField) ss) -> Producer (Record rs) m () -> m (FrameRec ss) -- | Convert a structure-of-arrays to an array-of-structures. This can -- simplify usage of an in-memory representation. toAoS :: Int -> Rec ((->) Int :. ElField) rs -> FrameRec rs -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generator a matter of indexing into a densely packed -- representation. inCore :: forall m n rs. (PrimMonad m, RecVec rs, Monad n) => Producer (Record rs) m () -> m (Producer (Record rs) n ()) -- | Build a Frame from a collection of Records using -- efficient column-based storage. toFrame :: (Foldable f, RecVec rs) => f (Record rs) -> Frame (Record rs) -- | Keep only those rows of a FrameRec that satisfy a predicate. filterFrame :: RecVec rs => (Record rs -> Bool) -> FrameRec rs -> FrameRec rs -- | Process a stream of Records into a stream of Frames that -- each contains no more than the given number of records. produceFrameChunks :: forall rs m. (RecVec rs, PrimMonad m) => Int -> Producer (Record rs) m () -> Producer (FrameRec rs) m () -- | Split a Frame into chunks of no more than the given number of -- records. The underlying memory is shared with the original -- Frame. frameChunks :: Int -> FrameRec rs -> [FrameRec rs] instance Frames.InCore.RecVec '[] instance (Data.Vector.Generic.Mutable.Base.MVector (Frames.InCore.VectorMFor a) a, Data.Vector.Generic.Base.Vector (Frames.InCore.VectorFor a) a, GHC.TypeLits.KnownSymbol s, Frames.InCore.RecVec rs) => Frames.InCore.RecVec ((s Frames.Col.:-> a) : rs) -- | Functions for performing SQL style table joins on Frame -- objects. Uses Data.Discrimination under the hood for O(n) joins. These -- have behaviour equivalent to INNER JOIN, FULL JOIN, -- LEFT JOIN, and RIGHT JOIN from SQL. module Frames.Joins -- | Perform an inner join operation on two frames. -- -- Requires the language extension TypeApplications for -- specifying the columns to join on. -- -- Joins can be done on on one or more columns provided the matched -- columns have a Grouping instance, most simple types do. -- -- Presently join columns must be present and named identically in both -- left and right frames. -- -- Basic usage: innerJoin @'[JoinCol1, ..., JoinColN] leftFrame -- rightFrame innerJoin :: forall fs rs rs2 rs2'. (fs ⊆ rs, fs ⊆ rs2, rs ⊆ (rs ++ rs2'), rs2' ⊆ rs2, rs2' ~ RDeleteAll fs rs2, Grouping (Record fs), RecVec rs, RecVec rs2', RecVec (rs ++ rs2')) => Frame (Record rs) -> Frame (Record rs2) -> Frame (Record (rs ++ rs2')) -- | Perform an outer join (FULL JOIN) operation on two frames. -- -- Requires the use the language extension TypeApplications for -- specifying the columns to join on. -- -- Joins can be done on on one or more columns provided the columns have -- a Grouping instance, most simple types do. -- -- Presently join columns must be present and named identically in both -- left and right frames. -- -- Returns a list of Records in the Maybe interpretation functor. If a -- key in the left table is missing from the right table, non-key columns -- from the right table are filled with Nothing. If a key in the -- right table is missing from the left table, non-key columns from the -- right table are filled with Nothing. -- -- Basic usage: outerJoin @'[JoinCol1, ..., JoinColN] leftFrame -- rightFrame outerJoin :: forall fs rs rs' rs2 rs2' ors. (fs ⊆ rs, fs ⊆ rs2, rs ⊆ (rs ++ rs2'), rs' ⊆ rs, rs' ~ RDeleteAll fs rs, rs2' ⊆ rs2, rs2' ~ RDeleteAll fs rs2, ors ~ (rs ++ rs2'), ors :~: (rs' ++ rs2), RecApplicative rs2', RecApplicative rs, RecApplicative rs', Grouping (Record fs), RMap rs, RMap rs2, RMap ors, RecVec rs, RecVec rs2', RecVec ors) => Frame (Record rs) -> Frame (Record rs2) -> [Rec (Maybe :. ElField) ors] -- | Perform an left join operation on two frames. -- -- Requires the language extension TypeApplications for -- specifying the columns to join on. -- -- Joins can be done on on one or more columns provided the columns have -- a Grouping instance, most simple types do. -- -- Presently join columns must be present and named identically in both -- left and right frames. -- -- Returns a list of Records in the Maybe interpretation functor. If a -- key in the left table is missing from the right table, non-key columns -- from the right table are filled with Nothing. -- -- Basic usage: leftJoin @'[JoinCol1, ..., JoinColN] leftFrame -- rightFrame leftJoin :: forall fs rs rs2 rs2'. (fs ⊆ rs, fs ⊆ rs2, rs ⊆ (rs ++ rs2'), rs2' ⊆ rs2, rs2' ~ RDeleteAll fs rs2, RMap rs, RMap (rs ++ rs2'), RecApplicative rs2', Grouping (Record fs), RecVec rs, RecVec rs2', RecVec (rs ++ rs2')) => Frame (Record rs) -> Frame (Record rs2) -> [Rec (Maybe :. ElField) (rs ++ rs2')] -- | Perform an right join operation on two frames. -- -- Requires the language extension TypeApplications for -- specifying the columns to join on. -- -- Joins can be done on on one or more columns provided the columns have -- a Grouping instance, most simple types do. -- -- Presently join columns must be present and named identically in both -- left and right frames. -- -- Returns a list of Records in the Maybe interpretation functor. If a -- key in the right table is missing from the left table, non-key columns -- from the right table are filled with Nothing. -- -- Basic usage: rightJoin @'[JoinCol1, ..., JoinColN] leftFrame -- rightFrame rightJoin :: forall fs rs rs' rs2 rs2' ors. (fs ⊆ rs, fs ⊆ rs2, rs ⊆ (rs ++ rs2'), rs' ⊆ rs, rs' ~ RDeleteAll fs rs, rs2' ⊆ rs2, rs2' ~ RDeleteAll fs rs2, ors ~ (rs ++ rs2'), ors :~: (rs' ++ rs2), RecApplicative rs2', RecApplicative rs, RecApplicative rs', Grouping (Record fs), RMap rs2, RMap ors, RecVec rs, RecVec rs2', RecVec ors) => Frame (Record rs) -> Frame (Record rs2) -> [Rec (Maybe :. ElField) ors] -- | Support for representing so-called categorical variables: a (usually -- small) finite set of textual values. We map these onto regular Haskell -- data types and offer help to generate useful type class instances for -- such types. module Frames.Categorical -- | A categorical variable can take on one of a finite number of textual -- names. Any value of type Categorical n has no more than -- n variants. newtype Categorical (n :: Nat) Categorical :: Set Text -> Categorical [categories] :: Categorical -> Set Text -- | Ensure the first character of a String is uppercase. cap :: String -> String -- | Helper for working with derivingUnbox. Takes the name of the -- type and the number of variants in the sum type in order to determine -- a compact representation. unboxDecls :: String -> Int -> DecsQ -- | Generate a splice with data type declaration and associated instances -- for type suitable for representing a categorical variable. This is a -- type that maps between a finite set of textual names and Haskell data -- constructors. Usage: declareCategorical typeName optionalConPrefix -- variantNames will produce a data type with name typeName -- and data constructors whose names are a concatenation of -- optionalConPrefix and each element of variantNames. declareCategorical :: String -> Maybe String -> [String] -> Q [Dec] instance GHC.Show.Show (Frames.Categorical.Categorical n) instance GHC.Classes.Eq (Frames.Categorical.Categorical n) instance GHC.TypeNats.KnownNat n => Frames.ColumnTypeable.Parseable (Frames.Categorical.Categorical n) module Frames.ColumnUniverse -- | Generalize algebraic sum types. data CoRec (a :: k -> Type) (b :: [k]) :: forall k. () => k -> Type -> [k] -> Type -- | A universe of common column variants. These are the default column -- types that Frames can infer. See the Tutorial for an -- example of extending the default types with your own. type Columns = ColumnUniverse CommonColumns -- | Define a set of variants that captures all possible column types. type ColumnUniverse = CoRec ColInfo -- | Information necessary for synthesizing row types and comparing types. data ColInfo a -- | Common column types: Bool, Int, Double, -- Text type CommonColumns = [Bool, Int, Double, Text] -- | Common column types including categorical types. type CommonColumnsCat = [Bool, Int, Double, Categorical 8, Text] parsedTypeRep :: ColInfo a -> Parsed Type instance GHC.Show.Show a => GHC.Show.Show (Frames.ColumnUniverse.ColInfo a) instance (Data.Text.Internal.Text Data.Vinyl.Lens.∈ ts, Data.Vinyl.Core.RPureConstrained Frames.ColumnTypeable.Parseable ts) => GHC.Base.Monoid (Data.Vinyl.CoRec.CoRec Frames.ColumnUniverse.ColInfo ts) instance (Data.Text.Internal.Text Data.Vinyl.Lens.∈ ts, Data.Vinyl.Core.RPureConstrained Frames.ColumnTypeable.Parseable ts) => GHC.Base.Semigroup (Data.Vinyl.CoRec.CoRec Frames.ColumnUniverse.ColInfo ts) instance (Data.Vinyl.Core.RPureConstrained Frames.ColumnTypeable.Parseable ts, Data.Vinyl.CoRec.FoldRec ts ts, Data.Vinyl.Core.RecApplicative ts, Data.Text.Internal.Text Data.Vinyl.Lens.∈ ts) => Frames.ColumnTypeable.ColumnTypeable (Data.Vinyl.CoRec.CoRec Frames.ColumnUniverse.ColInfo ts) module Frames.ExtraInstances instance (Frames.RecF.AllCols Data.Discrimination.Grouping.Grouping rs, Data.Discrimination.Grouping.Grouping (Frames.Rec.Record rs), Data.Discrimination.Grouping.Grouping (Data.Vinyl.Functor.ElField (s Frames.Col.:-> r)), Data.Discrimination.Grouping.Grouping r) => Data.Discrimination.Grouping.Grouping (Frames.Rec.Record ((s Frames.Col.:-> r) : rs)) instance Data.Discrimination.Grouping.Grouping (Frames.Rec.Record '[]) instance Data.Discrimination.Grouping.Grouping a => Data.Discrimination.Grouping.Grouping (Data.Vinyl.Functor.ElField (s Frames.Col.:-> a)) instance Data.Discrimination.Grouping.Grouping Data.Text.Internal.Text instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.Vinyl.Functor.Identity a) instance Control.DeepSeq.NFData1 Data.Vinyl.Functor.Identity instance forall a (f :: a -> *) (r :: a) (rs :: [a]). (Control.DeepSeq.NFData (f r), Control.DeepSeq.NFData (Data.Vinyl.Core.Rec f rs)) => Control.DeepSeq.NFData (Data.Vinyl.Core.Rec f (r : rs)) instance forall u (f :: u -> *). Control.DeepSeq.NFData (Data.Vinyl.Core.Rec f '[]) instance (Control.DeepSeq.NFData1 f, Control.DeepSeq.NFData1 g) => Control.DeepSeq.NFData1 (Data.Vinyl.Functor.Compose f g) instance forall k l (f :: l -> *) (g :: k -> l) (a :: k). Control.DeepSeq.NFData (f (g a)) => Control.DeepSeq.NFData (Data.Vinyl.Functor.Compose f g a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Frames.Frame.Frame a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.Vinyl.Functor.ElField (s Frames.Col.:-> a)) -- | Infer row types from comma-separated values (CSV) data and read that -- data from files. Template Haskell is used to generate the necessary -- types so that you can write type safe programs referring to those -- types. module Frames.CSV type Separator = Text type QuoteChar = Char data QuotingMode -- | No quoting enabled. The separator may not appear in values NoQuoting :: QuotingMode -- | Quoted values with the given quoting character. Quotes are escaped by -- doubling them. Mostly RFC4180 compliant, except doesn't support -- newlines in values RFC4180Quoting :: QuoteChar -> QuotingMode data ParserOptions ParserOptions :: Maybe [Text] -> Separator -> QuotingMode -> ParserOptions [headerOverride] :: ParserOptions -> Maybe [Text] [columnSeparator] :: ParserOptions -> Separator [quotingMode] :: ParserOptions -> QuotingMode -- | Default ParseOptions get column names from a header line, and -- use commas to separate columns. defaultParser :: ParserOptions -- | Default separator string. defaultSep :: Separator -- | Helper to split a Text on commas and strip leading and trailing -- whitespace from each resulting chunk. tokenizeRow :: ParserOptions -> Text -> [Text] -- | Post processing applied to a list of tokens split by the separator -- which should have quoted sections reassembeld reassembleRFC4180QuotedParts :: Separator -> QuoteChar -> [Text] -> [Text] -- | Infer column types from a prefix (up to 1000 lines) of a CSV file. prefixInference :: (ColumnTypeable a, Monoid a, Monad m) => Parser [Text] m [a] -- | Extract column names and inferred types from a CSV file. readColHeaders :: (ColumnTypeable a, Monoid a, Monad m) => ParserOptions -> Producer [Text] m () -> m [(Text, a)] -- | Parsing each component of a RecF from a list of text chunks, -- one chunk per record component. class ReadRec rs readRec :: ReadRec rs => [Text] -> Rec (Either Text :. ElField) rs -- | Opens a file (in MonadSafe) and repeatedly applies the given -- function to the Handle to obtain lines to yield. Adapted from -- the moribund pipes-text package. pipeLines :: MonadSafe m => (Handle -> IO (Either IOException Text)) -> FilePath -> Producer Text m () -- | Produce lines of Text. produceTextLines :: MonadSafe m => FilePath -> Producer Text m () -- | Produce lines of tokens that were separated by the given separator. produceTokens :: MonadSafe m => FilePath -> Separator -> Producer [Text] m () -- | Consume lines of Text, writing them to a file. consumeTextLines :: MonadSafe m => FilePath -> Consumer Text m r -- | Produce the lines of a latin1 (or ISO8859 Part 1) encoded file as -- ’T.Text’ values. readFileLatin1Ln :: MonadSafe m => FilePath -> Producer [Text] m () -- | Read a RecF from one line of CSV. readRow :: ReadRec rs => ParserOptions -> Text -> Rec (Either Text :. ElField) rs -- | Produce rows where any given entry can fail to parse. readTableMaybeOpt :: (MonadSafe m, ReadRec rs, RMap rs) => ParserOptions -> FilePath -> Producer (Rec (Maybe :. ElField) rs) m () -- | Stream lines of CSV data into rows of ’Rec’ values values where any -- given entry can fail to parse. pipeTableMaybeOpt :: (Monad m, ReadRec rs, RMap rs) => ParserOptions -> Pipe [Text] (Rec (Maybe :. ElField) rs) m () -- | 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 raw -- Text of that entry is retained. pipeTableEitherOpt :: (Monad m, ReadRec rs) => ParserOptions -> Pipe Text (Rec (Either Text :. ElField) rs) m () -- | Produce rows where any given entry can fail to parse. readTableMaybe :: (MonadSafe m, ReadRec rs, RMap rs) => FilePath -> Producer (Rec (Maybe :. ElField) rs) m () -- | 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) => Pipe [Text] (Rec (Maybe :. ElField) rs) m () -- | 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 raw -- Text of that entry is retained. pipeTableEither :: (Monad m, ReadRec rs) => Pipe Text (Rec (Either Text :. ElField) rs) m () -- | Returns a producer of rows for which each column was successfully -- parsed. readTableOpt :: (MonadSafe m, ReadRec rs, RMap rs) => ParserOptions -> FilePath -> Producer (Record rs) m () -- | Pipe lines of CSV text into rows for which each column was -- successfully parsed. pipeTableOpt :: (ReadRec rs, RMap rs, Monad m) => ParserOptions -> Pipe [Text] (Record rs) m () -- | Returns a producer of rows for which each column was successfully -- parsed. readTable :: (MonadSafe m, ReadRec rs, RMap rs) => FilePath -> Producer (Record rs) m () -- | Pipe lines of CSV text into rows for which each column was -- successfully parsed. pipeTable :: (ReadRec rs, RMap rs, Monad m) => Pipe [Text] (Record rs) m () showFieldsCSV :: (RecMapMethod ShowCSV ElField ts, RecordToList ts) => Record ts -> [Text] -- | yield a header row with column names followed by a line of text -- for each Record with each field separated by a comma. If your -- source of Record values is a Producer, consider using -- pipeToCSV to keep everything streaming. produceCSV :: forall f ts m. (ColumnHeaders ts, Foldable f, Monad m, RecordToList ts, RecMapMethod ShowCSV ElField ts) => f (Record ts) -> Producer String m () -- | yield a header row with column names followed by a line of text -- for each Record with each field separated by a comma. This is -- the same as produceCSV, but adapated for cases where you have -- streaming input that you wish to use to produce streaming output. pipeToCSV :: forall ts m. (Monad m, ColumnHeaders ts, RecordToList ts, RecMapMethod ShowCSV ElField ts) => Pipe (Record ts) Text m () -- | Write a header row with column names followed by a line of text for -- each Record to the given file. writeCSV :: (ColumnHeaders ts, Foldable f, RecordToList ts, RecMapMethod ShowCSV ElField ts) => FilePath -> f (Record ts) -> IO () instance GHC.Show.Show Frames.CSV.ParserOptions instance GHC.Classes.Eq Frames.CSV.ParserOptions instance GHC.Show.Show Frames.CSV.QuotingMode instance GHC.Classes.Eq Frames.CSV.QuotingMode instance Frames.CSV.ReadRec '[] instance (Frames.ColumnTypeable.Parseable t, Frames.CSV.ReadRec ts, GHC.TypeLits.KnownSymbol s) => Frames.CSV.ReadRec ((s Frames.Col.:-> t) : ts) instance Language.Haskell.TH.Syntax.Lift Frames.CSV.ParserOptions instance Language.Haskell.TH.Syntax.Lift Frames.CSV.QuotingMode -- | Code generation of types relevant to Frames use-cases. Generation may -- be driven by an automated inference process or manual use of the -- individual helpers. module Frames.TH -- | Generate a column type. recDec :: [Type] -> Type -- | Capitalize the first letter of a Text. capitalize1 :: Text -> Text -- | Massage a column name from a CSV file into a valid Haskell type -- identifier. sanitizeTypeName :: Text -> Text -- | Declare a type synonym for a column. mkColSynDec :: TypeQ -> Name -> DecQ -- | Declare lenses for working with a column. mkColLensDec :: Name -> Type -> Text -> DecsQ lowerHead :: Text -> Maybe Text -- | For each column, we declare a type synonym for its type, and a Proxy -- value of that type. colDec :: Text -> String -> Text -> Either (String -> Q [Dec]) Type -> Q (Type, [Dec]) -- | Splice for manually declaring a column of a given type. For example, -- declareColumn "x2" ''Double will declare a type synonym -- type X2 = "x2" :-> Double and a lens x2. declareColumn :: Text -> Name -> DecsQ -- | Splice for manually declaring a column of a given type in which the -- generated type synonym's name has a prefix applied to the column name. -- For example, declarePrefixedColumn "x2" "my" ''Double will -- declare a type synonym type MyX2 = "x2" :-> Double and a -- lens myX2. declarePrefixedColumn :: Text -> Text -> Name -> DecsQ -- | Control how row and named column types are generated. The type -- argument is a type-level list of the possible column types. data RowGen (a :: [Type]) RowGen :: [String] -> String -> Separator -> String -> Proxy a -> (Separator -> Producer [Text] (SafeT IO) ()) -> RowGen -- | Use these column names. If empty, expect a header row in the data file -- to provide column names. [columnNames] :: RowGen -> [String] -- | A common prefix to use for every generated declaration. [tablePrefix] :: RowGen -> String -- | The string that separates the columns on a row. [separator] :: RowGen -> Separator -- | The row type that enumerates all columns. [rowTypeName] :: RowGen -> String -- | A record field that mentions the phantom type list of possible column -- types. Having this field prevents record update syntax from losing -- track of the type argument. [columnUniverse] :: RowGen -> Proxy a -- | A producer of rows of ’T.Text’ values that were separated by a -- Separator value. [lineReader] :: RowGen -> Separator -> Producer [Text] (SafeT IO) () -- | A default RowGen. This instructs the type inference engine to -- get column names from the data file, use the default column separator -- (a comma), infer column types from the default Columns set of -- types, and produce a row type with name Row. rowGen :: FilePath -> RowGen CommonColumns -- | Like rowGen, but will also generate custom data types for -- Categorical variables with up to 8 distinct variants. rowGenCat :: FilePath -> RowGen CommonColumnsCat -- | Like tableType, but additionally generates a type synonym for -- each column, and a proxy value of that type. If the CSV file has -- column names "foo", "bar", and "baz", then this will declare type -- Foo = "foo" :-> Int, for example, foo = rlens @Foo, -- and foo' = rlens' @Foo. tableTypes :: String -> FilePath -> DecsQ -- | Inspect no more than this many lines when inferring column types. prefixSize :: Int -- | Generate a type for a row of a table. This will be something like -- Record ["x" :-> a, "y" :-> b, "z" :-> c]. Column -- type synonyms are not generated (see tableTypes'). -- tableType' :: forall a. (ColumnTypeable a, Monoid a) => RowGen a -- -> DecsQ tableType' (RowGen {..}) = pure . TySynD (mkName -- rowTypeName) [] $ (runIO (P.runSafeT (readColHeaders opts -- lineSource)) >>= recDec') where recDec' = recDec . map (second -- colType) :: [(T.Text, a)] -> Q Type colNames' | null columnNames = -- Nothing | otherwise = Just (map T.pack columnNames) opts = -- ParserOptions colNames' separator (RFC4180Quoting '"') lineSource = -- lineReader separator >-> P.take prefixSize -- -- Tokenize the first line of a ’P.Producer’. colNamesP :: Monad m => Producer [Text] m () -> m [Text] -- | Generate a type for a row of a table all of whose columns remain -- unparsed Text values. tableTypesText' :: forall a c. (c ~ CoRec ColInfo a, ColumnTypeable c, Monoid c) => RowGen a -> DecsQ -- | Generate a type for a row of a table. This will be something like -- Record ["x" :-> a, "y" :-> b, "z" :-> c]. -- Additionally generates a type synonym for each column, and a proxy -- value of that type. If the CSV file has column names "foo", "bar", and -- "baz", then this will declare type Foo = "foo" :-> Int, -- for example, foo = rlens @Foo, and foo' = rlens' -- @Foo. tableTypes' :: forall a c. (c ~ CoRec ColInfo a, ColumnTypeable c, Monoid c) => RowGen a -> DecsQ -- | User-friendly, type safe, runtime efficient tooling for working with -- tabular data deserialized from comma-separated values (CSV) files. The -- type of each row of data is inferred from data, which can then be -- streamed from disk, or worked with in memory. module Frames -- | ByteString and Text reading using MonadPlus to handle parse failure. -- On error, fromText and fromBS will return mzero. You can use mplus to -- provide fallback defaults. class Readable a -- | Reads data from a Text representation. fromText :: (Readable a, MonadPlus m) => Text -> m a -- | Reads data from a UTF8 encoded ByteString. The default implementation -- of this function simply decodes with UTF-8 and then calls the fromText -- function. If decoding fails, mzero will be returned. You can provide -- your own implementation if you need different behavior such as not -- decoding to UTF8. fromBS :: (Readable a, MonadPlus m) => ByteString -> m a -- | Takes a larger record to a smaller one by forgetting fields. This is -- rcastC with the type arguments reordered for more convenient -- usage with TypeApplications. rcast :: (RecSubset record rs ss is, RecSubsetFCtx record f) => record f ss -> record f rs -- | A lens into a slice of the larger record. This is rsubsetC with -- the type arguments reordered for more convenient usage with -- TypeApplications. rsubset :: (RecSubset record rs ss is, Functor g, RecSubsetFCtx record f) => (record f rs -> g (record f rs)) -> record f ss -> g (record f ss) -- | A shorthand for rappend. (<+>) :: () => Rec f as -> Rec f bs -> Rec f (as ++ bs) infixr 5 <+> -- | A record is parameterized by a universe u, an interpretation -- f and a list of rows rs. The labels or indices of -- the record are given by inhabitants of the kind u; the type -- of values at any label r :: u is given by its interpretation -- f r :: *. data Rec (a :: u -> Type) (b :: [u]) :: forall u. () => u -> Type -> [u] -> Type -- | A value with a phantom Symbol label. It is not a Haskell -- Functor, but it is used in many of the same places a -- Functor is used in vinyl. data ElField (field :: (Symbol, Type)) -- | Apply a type class method to a Field. Intended for use with -- TypeApplications, e.g. onField @Show show r. onField :: RPureConstrained c ts => (forall a. (a ∈ ts, c a) => a -> b) -> Field ts -> b -- | Apply methods from a type class to a CoRec. Intended for use -- with TypeApplications, e.g. onCoRec @Show show r onCoRec :: RPureConstrained c ts => (forall (a :: k2). (a ∈ ts, c a) => f a -> g b) -> CoRec f ts -> g b -- | A Field of a Rec Identity is a CoRec -- Identity. type Field = CoRec Identity -- | Lens for an ElField's data payload. rfield :: Functor f => (a -> f b) -> ElField ((,) s a) -> f (ElField ((,) s b)) type (:.) (f :: l -> Type) (g :: k -> l) = Compose f g infixr 9 :. -- | Remove the first occurence of a type from a type-level list. type family RDelete (r :: a) (rs :: [a]) :: [a] -- | A constraint-former which applies to every field in a record. type family RecAll (f :: u -> Type) (rs :: [u]) (c :: Type -> Constraint) :: Constraint -- | Constraint that all types in a type-level list satisfy a constraint. type family AllConstrained (c :: u -> Constraint) (ts :: [u]) :: Constraint -- | Constraint that each Constraint in a type-level list is satisfied by a -- particular type. class AllSatisfied (cs :: k) (t :: k1) -- | Constraint that all types in a type-level list satisfy each constraint -- from a list of constraints. -- -- AllAllSat cs ts should be equivalent to AllConstrained -- (AllSatisfied cs) ts if partial application of type families were -- legal. type family AllAllSat (cs :: k) (ts :: [k1]) :: Constraint type (a :: Symbol) :-> b = '(a, b) pattern Col :: KnownSymbol s => t -> ElField '(s, t) -- | Produce rows where any given entry can fail to parse. readTableMaybe :: (MonadSafe m, ReadRec rs, RMap rs) => FilePath -> Producer (Rec (Maybe :. ElField) rs) m () -- | 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) => Pipe [Text] (Rec (Maybe :. ElField) rs) m () -- | Returns a producer of rows for which each column was successfully -- parsed. readTableOpt :: (MonadSafe m, ReadRec rs, RMap rs) => ParserOptions -> FilePath -> Producer (Record rs) m () -- | Returns a producer of rows for which each column was successfully -- parsed. readTable :: (MonadSafe m, ReadRec rs, RMap rs) => FilePath -> Producer (Record rs) m () -- | Pipe lines of CSV text into rows for which each column was -- successfully parsed. pipeTable :: (ReadRec rs, RMap rs, Monad m) => Pipe [Text] (Record rs) m () -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generators a matter of indexing into a densely packed -- representation. Returns a Frame that provides a function to -- index into the table. inCoreAoS :: (PrimMonad m, MonadIO m, MonadMask m, RecVec rs) => Producer (Record rs) (SafeT m) () -> m (FrameRec rs) -- | Like inCoreAoS, but applies the provided function to the record -- of columns before building the Frame. inCoreAoS' :: (PrimMonad m, MonadIO m, MonadMask m, RecVec rs) => (Rec ((->) Int :. ElField) rs -> Rec ((->) Int :. ElField) ss) -> Producer (Record rs) (SafeT m) () -> m (FrameRec ss) -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generator a matter of indexing into a densely packed -- representation. inCore :: (PrimMonad m, MonadIO m, MonadMask m, RecVec rs, Monad n) => Producer (Record rs) (SafeT m) () -> m (Producer (Record rs) n ()) -- | Stream a finite sequence of rows into an efficient in-memory -- representation for further manipulation. Each column of the input -- table will be stored optimally based on its type, making use of the -- resulting generators a matter of indexing into a densely packed -- representation. Returns the number of rows and a record of column -- indexing functions. See toAoS to convert the result to a -- Frame which provides an easier-to-use function that indexes -- into the table in a row-major fashion. inCoreSoA :: (PrimMonad m, MonadIO m, MonadMask m, RecVec rs) => Producer (Record rs) (SafeT m) () -> m (Int, Rec ((->) Int :. ElField) rs) -- | Convert a structure-of-arrays to an array-of-structures. This can -- simplify usage of an in-memory representation. toAoS :: Int -> Rec ((->) Int :. ElField) rs -> FrameRec rs -- | Build a Frame from a collection of Records using -- efficient column-based storage. toFrame :: (Foldable f, RecVec rs) => f (Record rs) -> Frame (Record rs) -- | Keep only those rows of a FrameRec that satisfy a predicate. filterFrame :: RecVec rs => (Record rs -> Bool) -> FrameRec rs -> FrameRec rs -- | Like melt in the reshape2 package for the R -- language. It stacks multiple columns into a single column over -- multiple rows. Takes a specification of the id columns that remain -- unchanged. The remaining columns will be stacked. -- -- Suppose we have a record, r :: Record [Name,Age,Weight]. If -- we apply melt [pr1|Name|] r, we get two values with type -- Record [Name, "value" :-> CoRec Identity [Age,Weight]]. -- The first will contain Age in the value column, and -- the second will contain Weight in the value column. meltRow :: (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => proxy ss -> Record ts -> [Record (ss ++ '["value" :-> CoRec ElField vs])] -- | Applies meltRow to each row of a FrameRec. melt :: forall vs ts ss proxy. (vs ⊆ ts, ss ⊆ ts, vs ~ RDeleteAll ss ts, HasLength vs, Disjoint ss ts ~ 'True, ts ≅ (vs ++ ss), ColumnHeaders vs, RowToColumn vs vs) => proxy ss -> FrameRec ts -> FrameRec (ss ++ '["value" :-> CoRec ElField vs]) type family RecordColumns t -- | A record with unadorned values. This is Vinyl's Rec -- ElField. We give this type a name as it is used pervasively for -- records in Frames. type Record = FieldRec -- | A cons function for building Record values. (&:) :: KnownSymbol s => a -> Record rs -> Record ((s :-> a) : rs) infixr 5 &: -- | Separate the first element of a Record from the rest of the -- row. recUncons :: Record ((s :-> a) : rs) -> (a, Record rs) -- | Undistribute Maybe from a Rec Maybe. This is just -- a specific usage of rtraverse, but it is quite common. recMaybe :: Rec (Maybe :. ElField) cs -> Maybe (Record cs) -- | Show each field of a Record without its column name. showFields :: (RecMapMethod Show ElField ts, RecordToList ts) => Record ts -> [String] -- | Get the value of a field of a Record. This is intended for use -- with TypeApplications, as compared to rgetv that is -- intended for use with OverloadedLabels. rgetField :: forall t s a rs. (t ~ '(s, a), t ∈ rs) => Record rs -> a -- | Replace the value of a field of a Record. This is intended for -- use with TypeApplications, as compared to rputf that -- is intended for use with OverloadedLabels. rputField :: forall t s a rs. (t ~ '(s, a), t ∈ rs, KnownSymbol s) => a -> Record rs -> Record rs -- | Splice for manually declaring a column of a given type. For example, -- declareColumn "x2" ''Double will declare a type synonym -- type X2 = "x2" :-> Double and a lens x2. declareColumn :: Text -> Name -> DecsQ -- | Like tableType, but additionally generates a type synonym for -- each column, and a proxy value of that type. If the CSV file has -- column names "foo", "bar", and "baz", then this will declare type -- Foo = "foo" :-> Int, for example, foo = rlens @Foo, -- and foo' = rlens' @Foo. tableTypes :: String -> FilePath -> DecsQ -- | Generate a type for a row of a table. This will be something like -- Record ["x" :-> a, "y" :-> b, "z" :-> c]. -- Additionally generates a type synonym for each column, and a proxy -- value of that type. If the CSV file has column names "foo", "bar", and -- "baz", then this will declare type Foo = "foo" :-> Int, -- for example, foo = rlens @Foo, and foo' = rlens' -- @Foo. tableTypes' :: forall a c. (c ~ CoRec ColInfo a, ColumnTypeable c, Monoid c) => RowGen a -> DecsQ -- | Run SafeT in the base monad, executing all unreleased -- finalizers at the end of the computation -- -- Use runSafeP to safely flush all unreleased finalizers and -- ensure prompt finalization without exiting the Proxy monad. runSafeP :: (MonadMask m, MonadIO m) => Effect (SafeT m) r -> Effect' m r -- | Run the SafeT monad transformer, executing all unreleased -- finalizers at the end of the computation runSafeT :: (MonadMask m, MonadIO m) => SafeT m r -> m r -- | SafeT is a monad transformer that extends the base monad with -- the ability to register and release finalizers. -- -- All unreleased finalizers are called at the end of the SafeT -- block, even in the event of exceptions. data SafeT (m :: Type -> Type) r -- | MonadSafe lets you register and release -- finalizers that execute in a Base monad class (MonadCatch m, MonadMask m, MonadIO m, MonadIO Base m) => MonadSafe (m :: Type -> Type) -- | Run a self-contained ’Pipes.Effect’ and execute the finalizers -- associated with the ’SafeT’ transformer. runSafeEffect :: (MonadIO m, MonadMask m) => Effect (SafeT m) r -> m r -- | A space efficient, packed, unboxed Unicode text type. data Text