-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Encode and decode separated values (CSV, PSV, ...) -- -- -- sv (separated values) is a library for parsing, decoding, encoding, -- and printing CSV and similar formats (such as PSV, TSV, and many -- more). -- -- sv uses an Applicative combinator style for decoding and encoding, -- rather than a type class based approach. This means we can have -- multiple decoders for the same type, multiple combinators of the same -- type, and we never have to worry about orphan instances. These -- decoders can be stitched together from provided primitives and -- combinators, or you can build one from a parser from your favourite -- parser combinator library. -- -- For parsing, sv uses hw-dsv, a high performance streaming CSV -- parser based on rank-select data structures. sv works with UTF-8, and -- should work with CP-1252 as well. It does not work with UTF-16 or -- UTF-32. -- -- sv returns values for all errors that occur - not just the first. -- Errors have more structure than just a string, indicating what went -- wrong. -- -- sv tries not to be opinionated about how your data should look. We -- intend for the user to have a great degree of freedom to build the -- right decoder for their dataset. -- -- Parts of sv are intended to be imported as follows: -- --
--   import Data.Sv
--   import qualified Data.Sv.Decode as D
--   import qualified Data.Sv.Encode as E
--   
-- -- Examples: -- -- -- -- To get the best performance, the hw-dsv parser and its dependencies -- underlying sv should be compiled with the flag +bmi2 to -- enable . These libraries are: bits-extra, -- hw-rankselect, hw-rankselect-base, and -- hw-dsv. A simple way to set the flags for all of them when -- building with cabal is to include a cabal.project file in your project -- containing something like the following: -- --
--   packages: .
--   package bits-extra
--     flags: +bmi2
--   package hw-rankselect
--     flags: +bmi2
--   package hw-rankselect-base
--     flags: +bmi2
--   package hw-dsv
--     flags: +bmi2
--   
@package sv @version 1.0 -- | This module contains data structures, combinators, and primitives for -- decoding a CSV into a list of your Haskell datatype. -- -- A file can be read with parseDecodeFromFile. If you already -- have the text data in memory, it can be decoded with -- parseDecode. You will need a Decode for your desired -- type. -- -- A Decode can be built using the primitives in this file. -- Decode is an Applicative and an Alt, allowing for -- composition of these values with <*> and -- <!> -- -- The primitive Decodes in this file which use -- ByteString expect UTF-8 encoding. The Decode type has an -- instance of Profunctor, so you can lmap or -- alterInput to reencode on the way in. -- -- This module is intended to be imported qualified like so -- --
--   import qualified Data.Sv.Decode as D
--   
module Data.Sv.Decode module Data.Sv.Encode module Data.Sv.Parse -- | A ParseOptions informs the parser how to parse your file. -- -- A default is provided as defaultParseOptions, seen below. data ParseOptions ParseOptions :: Separator -> Headedness -> ParseOptions -- | Which separator does the file use? Usually this is comma, but -- it can also be pipe, or any other Word8 -- (Separator = Word8) [_separator] :: ParseOptions -> Separator -- | Whether there is a header row with column names or not. [_headedness] :: ParseOptions -> Headedness -- | Default parsing options. -- -- The default is a comma separator, with a header at the top of the -- file. defaultParseOptions :: ParseOptions -- | The default separator is comma. defaultSeparator :: Separator -- | The default is that a header is present. defaultHeadedness :: Headedness instance Data.Sv.Structure.Headedness.HasHeadedness Data.Sv.Parse.ParseOptions instance Data.Sv.Structure.Separator.HasSeparator Data.Sv.Parse.ParseOptions module Data.Sv.Structure -- | This module exports most of the other modules from the package. It is -- intended to be imported unqualified, along with some qualified imports -- for the Data.Sv.Decode and Data.Sv.Encode modules as -- needed. -- --
--   import Data.Sv
--   import qualified Data.Sv.Decode as D
--   import qualified Data.Sv.Encode as E
--   
module Data.Sv -- | Parse a ByteString as an Sv, and then decode it with the given -- decoder. parseDecode :: Decode' ByteString a -> ParseOptions -> ByteString -> DecodeValidation ByteString [a] -- | Load a file, parse it, and decode it. parseDecodeFromFile :: MonadIO m => Decode' ByteString a -> ParseOptions -> FilePath -> m (DecodeValidation ByteString [a]) -- | Decode from a DsvCursor parseDecodeFromDsvCursor :: Decode' ByteString a -> ParseOptions -> DsvCursor -> DecodeValidation ByteString [a] -- | Decodes a sv into a list of its values using the provided -- Decode decode :: Traversable f => Decode' ByteString a -> f Vector ByteString -> DecodeValidation ByteString f a -- | Build a Decode, given a function that returns Maybe. -- -- Return the given error if the function returns Nothing. decodeMay :: () => DecodeError e -> s -> Maybe a -> Decode e s a -- | Build a Decode, given a function that returns Either. decodeEither :: () => s -> Either DecodeError e a -> Decode e s a -- | Build a Decode, given a function that returns Either, -- and a function to build the error. decodeEither' :: () => e -> DecodeError e' -> s -> Either e a -> Decode e' s a -- | This can be used to build a Decode whose value depends on the -- result of another Decode. This is especially useful since -- Decode is not a Monad. -- -- If you need something like this but with more power, look at -- bindDecode (>>==) :: () => Decode e s a -> a -> DecodeValidation e b -> Decode e s b infixl 1 >>== -- | flipped >>== (==<<) :: () => a -> DecodeValidation e b -> Decode e s a -> Decode e s b infixr 1 ==<< -- | Encode the given list with the given Encode, configured by the -- given EncodeOptions. encode :: () => Encode a -> EncodeOptions -> [a] -> ByteString -- | Encode, writing to a file. This way is more efficient than encoding to -- a ByteString and then writing to file. encodeToFile :: () => Encode a -> EncodeOptions -> [a] -> FilePath -> IO () -- | Encode, writing the output to a file handle. encodeToHandle :: () => Encode a -> EncodeOptions -> [a] -> Handle -> IO () -- | Encode to a ByteString Builder, which is useful if you are -- going to combine the output with other ByteStrings. encodeBuilder :: () => Encode a -> EncodeOptions -> [a] -> Builder -- | Encode one row only encodeRow :: () => Encode a -> EncodeOptions -> a -> ByteString -- | Laws: -- --
--   <!> is associative:             (a <!> b) <!> c = a <!> (b <!> c)
--   <$> left-distributes over <!>:  f <$> (a <!> b) = (f <$> a) <!> (f <$> b)
--   
-- -- If extended to an Alternative then <!> should -- equal <|>. -- -- Ideally, an instance of Alt also satisfies the "left -- distributon" law of MonadPlus with respect to <.>: -- --
--   <.> right-distributes over <!>: (a <!> b) <.> c = (a <.> c) <!> (b <.> c)
--   
-- -- But Maybe, IO, Either a, -- ErrorT e m, and STM satisfy the alternative -- "left catch" law instead: -- --
--   pure a <!> b = pure a
--   
-- -- However, this variation cannot be stated purely in terms of the -- dependencies of Alt. -- -- When and if MonadPlus is successfully refactored, this class should -- also be refactored to remove these instances. -- -- The right distributive law should extend in the cases where the a -- Bind or Monad is provided to yield variations of the -- right distributive law: -- --
--   (m <!> n) >>- f = (m >>- f) <!> (m >>- f)
--   (m <!> n) >>= f = (m >>= f) <!> (m >>= f)
--   
class Functor f => Alt (f :: * -> *) -- | <|> without a required empty () :: Alt f => f a -> f a -> f a some :: (Alt f, Applicative f) => f a -> f [a] many :: (Alt f, Applicative f) => f a -> f [a] -- | The class of contravariant functors. -- -- Whereas in Haskell, one can think of a Functor as containing or -- producing values, a contravariant functor is a functor that can be -- thought of as consuming values. -- -- As an example, consider the type of predicate functions a -> -- Bool. One such predicate might be negative x = x < 0, -- which classifies integers as to whether they are negative. However, -- given this predicate, we can re-use it in other situations, providing -- we have a way to map values to integers. For instance, we can -- use the negative predicate on a person's bank balance to work -- out if they are currently overdrawn: -- --
--   newtype Predicate a = Predicate { getPredicate :: a -> Bool }
--   
--   instance Contravariant Predicate where
--     contramap f (Predicate p) = Predicate (p . f)
--                                            |   `- First, map the input...
--                                            `----- then apply the predicate.
--   
--   overdrawn :: Predicate Person
--   overdrawn = contramap personBankBalance negative
--   
-- -- Any instance should be subject to the following laws: -- --
--   contramap id = id
--   contramap f . contramap g = contramap (g . f)
--   
-- -- Note, that the second law follows from the free theorem of the type of -- contramap and the first law, so you need only check that the -- former condition holds. class Contravariant (f :: * -> *) contramap :: Contravariant f => a -> b -> f b -> f a -- | Replace all locations in the output with the same value. The default -- definition is contramap . const, but this may -- be overridden with a more efficient version. (>$) :: Contravariant f => b -> f b -> f a -- | A Divisible contravariant functor is the contravariant analogue -- of Applicative. -- -- Continuing the intuition that Contravariant functors consume -- input, a Divisible contravariant functor also has the ability -- to be composed "beside" another contravariant functor. -- -- Serializers provide a good example of Divisible contravariant -- functors. To begin let's start with the type of serializers for -- specific types: -- --
--   newtype Serializer a = Serializer { runSerializer :: a -> ByteString }
--   
-- -- This is a contravariant functor: -- --
--   instance Contravariant Serializer where
--     contramap f s = Serializer (runSerializer s . f)
--   
-- -- That is, given a serializer for a (s :: Serializer -- a), and a way to turn bs into as (a mapping -- f :: b -> a), we have a serializer for b: -- contramap f s :: Serializer b. -- -- Divisible gives us a way to combine two serializers that focus on -- different parts of a structure. If we postulate the existance of two -- primitive serializers - string :: Serializer String and -- int :: Serializer Int, we would like to be able to combine -- these into a serializer for pairs of Strings and -- Ints. How can we do this? Simply run both serializer and -- combine their output! -- --
--   data StringAndInt = StringAndInt String Int
--   
--   stringAndInt :: Serializer StringAndInt
--   stringAndInt = Serializer $ \(StringAndInt s i) ->
--     let sBytes = runSerializer string s
--         iBytes = runSerializer int i
--     in sBytes <> iBytes
--   
-- -- divide is a generalization by also taking a contramap -- like function to split any a into a pair. This conveniently -- allows you to target fields of a record, for instance, by extracting -- the values under two fields and combining them into a tuple. -- -- To complete the example, here is how to write stringAndInt -- using a Divisible instance: -- --
--   instance Divisible Serializer where
--     conquer = Serializer (const mempty)
--   
--     divide toBC bSerializer cSerializer = Serializer $ \a ->
--       case toBC a of
--         (b, c) ->
--           let bBytes = runSerializer bSerializer b
--               cBytes = runSerializer cSerializer c
--           in bBytes <> cBytes
--   
--   stringAndInt :: Serializer StringAndInt
--   stringAndInt =
--     divide (\(StringAndInt s i) -> (s, i)) string int
--   
class Contravariant f => Divisible (f :: * -> *) divide :: Divisible f => a -> (b, c) -> f b -> f c -> f a -- | Conquer acts as an identity for combining Divisible functors. conquer :: Divisible f => f a -- |
--   divided = divide id
--   
divided :: Divisible f => f a -> f b -> f (a, b) -- | A Decidable contravariant functor is the contravariant analogue -- of Alternative. -- -- Noting the superclass constraint that f must also be -- Divisible, a Decidable functor has the ability to "fan -- out" input, under the intuition that contravariant functors consume -- input. -- -- In the dicussion for Divisible, an example was demonstrated -- with Serializers, that turn as into -- ByteStrings. Divisible allowed us to serialize the -- product of multiple values by concatenation. By making our -- Serializer also Decidable- we now have the ability -- to serialize the sum of multiple values - for example different -- constructors in an ADT. -- -- Consider serializing arbitrary identifiers that can be either -- Strings or Ints: -- --
--   data Identifier = StringId String | IntId Int
--   
-- -- We know we have serializers for Strings and Ints, -- but how do we combine them into a Serializer for -- Identifier? Essentially, our Serializer needs to -- scrutinise the incoming value and choose how to serialize it: -- --
--   identifier :: Serializer Identifier
--   identifier = Serializer $ \identifier ->
--     case identifier of
--       StringId s -> runSerializer string s
--       IntId i -> runSerializer int i
--   
-- -- It is exactly this notion of choice that Decidable encodes. -- Hence if we add an instance of Decidable for -- Serializer... -- --
--   instance Decidable Serializer where
--     lose f = Serializer $ \a -> absurd (f a)
--     choose split l r = Serializer $ \a ->
--       either (runSerializer l) (runSerializer r) (split a)
--   
-- -- Then our identifier Serializer is -- --
--   identifier :: Serializer Identifier
--   identifier = choose toEither string int where
--     toEither (StringId s) = Left s
--     toEither (IntId i) = Right i
--   
class Divisible f => Decidable (f :: * -> *) -- | Acts as identity to choose. lose :: Decidable f => a -> Void -> f a choose :: Decidable f => a -> Either b c -> f b -> f c -> f a -- |
--   chosen = choose id
--   
chosen :: Decidable f => f b -> f c -> f Either b c -- | An Validation is either a value of the type err or -- a, similar to Either. However, the Applicative -- instance for Validation accumulates errors using a -- Semigroup on err. In contrast, the -- Applicative for Either returns only the first error. -- -- A consequence of this is that Validation has no Bind -- or Monad instance. This is because such an instance would -- violate the law that a Monad's ap must equal the -- Applicative's <*> -- -- An example of typical usage can be found here. data Validation err a Failure :: err -> Validation err a Success :: a -> Validation err a