Hoogle Search

Within LTS Haskell 24.52 (ghc-9.10.3)

Note that Stackage only displays results for the latest LTS and Nightly snapshot. Learn more.

  1. data PeekState

    store-core Data.Store.Core

    Holds a peekStatePtr, which is passed in to each Peek action. If the package is built with the 'force-alignment' flag, this also has a hidden Ptr field, which is used as scratch space during unaligned reads.

  2. newtype Poke a

    store-core Data.Store.Core

    Poke actions are useful for building sequential serializers. They are actions which write values to bytes into memory specified by a Ptr base. The Applicative and Monad instances make it easy to write serializations, by keeping track of the Offset of the current byte. They allow you to chain Poke action such that subsequent Pokes write into subsequent portions of the output.

  3. Poke :: (PokeState -> Offset -> IO (Offset, a)) -> Poke a

    store-core Data.Store.Core

    No documentation available.

  4. data PokeException

    store-core Data.Store.Core

    Exception thrown while running poke. Note that other types of exceptions could also be thrown. Invocations of fail in the Poke monad causes this exception to be thrown. PokeExceptions are not expected to occur in ordinary circumstances, and usually indicate a programming error.

  5. PokeException :: Offset -> Text -> PokeException

    store-core Data.Store.Core

    No documentation available.

  6. data PokeState

    store-core Data.Store.Core

    Holds a pokeStatePtr, which is passed in to each Poke action. If the package is built with the 'force-alignment' flag, this also has a hidden Ptr field, which is used as scratch space during unaligned writes.

  7. module Streamly.Data.Parser

    Parsers are stream consumers like folds with the following differences:

    • folds cannot fail but parsers can fail and backtrack.
    • folds can be composed as a Tee but parsers cannot.
    • folds can be used for scanning but parsers cannot.
    • folds can be converted to parsers.
    This module implements parsers with stream fusion which compile to efficient loops comparable to the speed of C.

    Using Parsers

    This module provides elementary parsers and parser combinators that can be used to parse a stream of data. Additionally, all the folds from the Streamly.Data.Fold module can be converted to parsers using fromFold. All the parsing functionality provided by popular parsing libraries, and more is available. Also see Streamly.Unicode.Parser module for Char stream parsers. A data stream can be transformed to a stream of parsed data elements. Parser combinators can be used to create a pipeline of folds or parsers such that the next fold or parser consumes the result of the previous parser. See parse and parseMany to run these parsers on a stream.

    Parser vs ParserK

    There are two functionally equivalent parsing modules, Streamly.Data.Parser (this module) and Streamly.Data.ParserK. The latter is a CPS based wrapper over the former, and can be used for parsing in general. Streamly.Data.Parser enables stream fusion and should be preferred over Streamly.Data.ParserK for high performance stream parsing use cases. However, there are a few cases where this module is not suitable and ParserK should be used instead. For static fusion, parser combinators have to use strict pattern matching on arguments of type Parser. This leads to infinte loop when a parser is defined recursively, due to strict evaluation of the recursive call. For example, the following implementation loops infinitely because of the recursive use of parser p in the *> combinator:
    >>> import Streamly.Data.Parser (Parser)
    
    >>> import qualified Streamly.Data.Fold as Fold
    
    >>> import qualified Streamly.Data.Parser as Parser
    
    >>> import qualified Streamly.Data.Stream as Stream
    
    >>> import Control.Applicative ((<|>))
    
    >>> :{
    
    >>> p :: Monad m => Parser Char m String
    
    >>> p = Parser.satisfy (== '(') *> p <|> Parser.fromFold Fold.toList
    
    >>> :}
    
    Use ParserK when recursive use is required:
    >>> import Streamly.Data.ParserK (ParserK)
    
    >>> import qualified Streamly.Data.StreamK as StreamK
    
    >>> import qualified Streamly.Internal.Data.StreamK as StreamK (parse)
    
    >>> import qualified Streamly.Internal.Data.ParserK as ParserK (adapt)
    
    >>> :{
    
    >>> p :: Monad m => ParserK Char m String
    
    >>> p = ParserK.adapt (Parser.satisfy (== '(')) *> p <|> ParserK.adapt (Parser.fromFold Fold.toList)
    
    >>> :}
    
    >>> StreamK.parse p $ StreamK.fromStream $ Stream.fromList "hello"
    Right "hello"
    
    For this reason Applicative, Alternative or Monad compositions with recursion cannot be used with the Parser type. Alternative type class based operations like asum and Alternative based generic parser combinators use recursion. Similarly, Applicative type class based operations like sequence use recursion. Custom implementations of many such operations are provided in this module (e.g. some, many), and those should be used instead. Another limitation of Parser type is due to the quadratic complexity causing slowdown when too many nested compositions are used. Especially Applicative, Monad, Alternative instances, and sequenced parsing operations (e.g. nested one, and splitWith) degrade the performance quadratically (O(n^2)) when combined n times, roughly 8 or less sequenced parsers are fine. READ THE DOCS OF APPLICATIVE, MONAD AND ALTERNATIVE INSTANCES.

    Streaming Parsers

    With ParserK you can use the generic Alternative type class based parsers from the parser-combinators library or similar. However, we recommend that you use the equivalent functionality from this module for better performance and for streaming behavior. Firstly, the combinators in this module are faster due to stream fusion. Secondly, these are streaming in nature as the results can be passed directly to other stream consumers (folds or parsers). The Alternative type class based parsers would end up buffering all the results in lists before they can be consumed. When recursion or heavy nesting is needed use ParserK.

    Error Reporting

    These parsers do not report the error context (e.g. line number or column). This may be supported in future.

    Monad Transformer Stack

    MonadTrans instance is not provided. If the Parser type is the top most layer (which should be the case almost always) you can just use fromEffect to execute the lower layer monad effects.

    Parser vs ParserK Implementation

    The Parser type represents a stream consumer by composing state as data which enables stream fusion. Stream fusion generates a tight loop without any constructor allocations between the stages, providing C like performance for the loop. Stream fusion works when multiple functions are combined in a pipeline statically. Therefore, the operations in this module must be inlined and must not be used recursively to allow for stream fusion. The ParserK type represents a stream consumer by composing function calls, therefore, a function call overhead is incurred at each composition. It is quite fast in general but may be a few times slower than a fused parser. However, it allows for scalable dynamic composition especially parsers can be used in recursive calls. Using the ParserK type operations like splitWith provide linear (O(n)) performance with respect to the number of compositions.

    Experimental APIs

    Please refer to Streamly.Internal.Data.Parser for functions that have not yet been released.

  8. data Parser a (m :: Type -> Type) b

    streamly-core Streamly.Data.Parser

    A parser is a fold that can fail and is represented as Parser step initial extract. Before we drive a parser we call the initial action to retrieve the initial state of the fold. The parser driver invokes step with the state returned by the previous step and the next input element. It results into a new state and a command to the driver represented by Step type. The driver keeps invoking the step function until it stops or fails. At any point of time the driver can call extract to inspect the result of the fold. If the parser hits the end of input extract is called. It may result in an error or an output value. Pre-release

  9. module Streamly.Data.ParserK

    See the general notes about parsing in the Streamly.Data.Parser module. This module implements a using Continuation Passing Style (CPS) wrapper over the Streamly.Data.Parser module. It is as fast or faster than attoparsec.

    Parser vs ParserK

    ParserK is preferred over Parser when extensive applicative, alternative and monadic composition is required, or when recursive or dynamic composition of parsers is required. The Parser type fuses statically and creates efficient loops whereas ParserK uses function call based composition and has comparatively larger runtime overhead but it is better suited to the specific use cases mentioned above. ParserK also allows to efficient parse a stream of arrays, it can also break the input stream into a parse result and remaining stream so that the stream can be parsed independently in segments.

    Using ParserK

    All the parsers from the Streamly.Data.Parser module can be adapted to ParserK using the adaptC, adapt, and adaptCG combinators. parseChunks runs a parser on a stream of unboxed arrays, this is the preferred and most efficient way to parse chunked input. The more general parseBreakChunks function returns the remaining stream as well along with the parse result. There are parseChunksGeneric, parseBreakChunksGeneric as well to run parsers on boxed arrays. parse, parseBreak run parsers on a stream of individual elements instead of stream of arrays.

    Monadic Composition

    Monad composition can be used for lookbehind parsers, we can dynamically compose new parsers based on the results of the previously parsed values. If we have to parse "a9" or "9a" but not "99" or "aa" we can use the following non-monadic, backtracking parser:
    >>> digits p1 p2 = ((:) <$> p1 <*> ((:) <$> p2 <*> pure []))
    
    >>> :{
    backtracking :: Monad m => ParserK Char m String
    backtracking = ParserK.adapt $
    digits (Parser.satisfy isDigit) (Parser.satisfy isAlpha)
    <|>
    digits (Parser.satisfy isAlpha) (Parser.satisfy isDigit)
    :}
    
    We know that if the first parse resulted in a digit at the first place then the second parse is going to fail. However, we waste that information and parse the first character again in the second parse only to know that it is not an alphabetic char. By using lookbehind in a Monad composition we can avoid redundant work:
    >>> data DigitOrAlpha = Digit Char | Alpha Char
    
    >>> :{
    lookbehind :: Monad m => ParserK Char m String
    lookbehind = do
    x1 <- ParserK.adapt $
    Digit <$> Parser.satisfy isDigit
    <|> Alpha <$> Parser.satisfy isAlpha
    -- Note: the parse depends on what we parsed already
    x2 <- ParserK.adapt $
    case x1 of
    Digit _ -> Parser.satisfy isAlpha
    Alpha _ -> Parser.satisfy isDigit
    return $ case x1 of
    Digit x -> [x,x2]
    Alpha x -> [x,x2]
    :}
    

    Experimental APIs

    Please refer to Streamly.Internal.Data.ParserK for functions that have not yet been released.

  10. data ParserK a (m :: Type -> Type) b

    streamly-core Streamly.Data.ParserK

    A continuation passing style parser representation. A continuation of Steps, each step passes a state and a parse result to the next Step. The resulting Step may carry a continuation that consumes input a and results in another Step. Essentially, the continuation may either consume input without a result or return a result with no further input to be consumed.

Page 1054 of many | Previous | Next