@@ -203,7 +203,8 @@ where
203203
204204import Control.Applicative (Alternative(..), liftA2)
205205import Control.Exception (Exception(..))
206−import Control.Monad (MonadPlus(..), (>=>))
206+-- import Control.Monad (MonadPlus(..), (>=>))
207+import Control.Monad ((>=>))
207208import Control.Monad.IO.Class (MonadIO, liftIO)
208209import Data.Bifunctor (Bifunctor(..))
209210import Fusion.Plugin.Types (Fuse(..))
@@ -218,7 +219,9 @@ import Prelude hiding (concatMap, filter)
218219-- >>> :m
219220-- >>> import Control.Applicative ((<|>))
220221-- >>> import Data.Bifunctor (second)
221−-- >>> import Prelude hiding (concatMap)
222+-- >>> import Prelude hiding (concatMap, span)
223+-- >>> import Streamly.Data.Fold (Fold)
224+-- >>> import Streamly.Data.Parser (Parser)
222225-- >>> import qualified Streamly.Data.Fold as Fold
223226-- >>> import qualified Streamly.Data.Stream as Stream
224227-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse)
@@ -492,16 +495,17 @@ data SeqParseState sl f sr = SeqParseL !sl | SeqParseR !f !sr
492495-- cannot scale to a large number of compositions. After around 100
493496-- compositions the performance starts dipping rapidly beyond a CPS style
494497-- unfused implementation.
495−
496−-- | Sequential parser application. Apply two parsers sequentially to an input
497−-- stream. The input is provided to the first parser, when it is done the
498−-- remaining input is provided to the second parser. If both the parsers
499−-- succeed their outputs are combined using the supplied function. The
500−-- operation fails if any of the parsers fail.
501498--
502499-- Note: This is a parsing dual of appending streams using
503−-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and zips
504−-- the results.
500+-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and
501+-- zips the results.
502+
503+-- | Sequential parser application.
504+--
505+-- Apply two parsers sequentially to an input stream. The first parser runs and
506+-- processes the input, the remaining input is then passed to the second
507+-- parser. If both parsers succeed, their outputs are combined using the
508+-- supplied function. If either parser fails, the operation fails.
505509--
506510-- This implementation is strict in the second argument, therefore, the
507511-- following will fail:
@@ -510,28 +514,15 @@ data SeqParseState sl f sr = SeqParseL !sl | SeqParseR !f !sr
510514-- *** Exception: Prelude.undefined
511515-- ...
512516--
513−-- Compare with 'Applicative' instance method '<*>'. This implementation allows
514−-- stream fusion but has quadratic complexity. This can fuse with other
515−-- operations and can be faster than 'Applicative' instance for small number
516−-- (less than 8) of compositions.
517−--
518−-- Many combinators can be expressed using @splitWith@ and other parser
519−-- primitives. Some common idioms are described below,
517+-- Although this implementation allows stream fusion, it has quadratic
518+-- complexity, making it suitable only for a small number of compositions.
519+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
520520--
521−-- @
522−-- span :: (a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
523−-- span pred f1 f2 = splitWith (,) ('takeWhile' pred f1) ('fromFold' f2)
524−-- @
521+-- Below are some common idioms that can be expressed using 'splitWith' and
522+-- other parser primitives:
525523--
526−-- @
527−-- spanBy :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
528−-- spanBy eq f1 f2 = splitWith (,) ('groupBy' eq f1) ('fromFold' f2)
529−-- @
530−--
531−-- @
532−-- spanByRolling :: (a -> a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
533−-- spanByRolling eq f1 f2 = splitWith (,) ('groupByRolling' eq f1) ('fromFold' f2)
534−-- @
524+-- >>> span p f1 f2 = Parser.splitWith (,) (Parser.takeWhile p f1) (Parser.fromFold f2)
525+-- >>> spanBy eq f1 f2 = Parser.splitWith (,) (Parser.groupBy eq f1) (Parser.fromFold f2)
535526--
536527-- /Pre-release/
537528--
@@ -695,10 +686,9 @@ data SeqAState sl sr = SeqAL !sl | SeqAR !sr
695686-- *** Exception: Prelude.undefined
696687-- ...
697688--
698−-- Compare with 'Applicative' instance method '*>'. This implementation allows
699−-- stream fusion but has quadratic complexity. This can fuse with other
700−-- operations, and can be faster than 'Applicative' instance for small
701−-- number (less than 8) of compositions.
689+-- Although this implementation allows stream fusion, it has quadratic
690+-- complexity, making it suitable only for a small number of compositions.
691+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
702692--
703693-- /Pre-release/
704694--
@@ -836,9 +826,10 @@ data AltParseState sl sr = AltParseL !Int !sl | AltParseR !sr
836826-- each subsequent alternative's input element has to go through, therefore, it
837827-- cannot scale to a large number of compositions
838828
839−-- | Sequential alternative. Apply the input to the first parser and return the
840−-- result if the parser succeeds. If the first parser fails then backtrack and
841−-- apply the same input to the second parser and return the result.
829+-- | Sequential alternative. The input is first passed to the first parser, and
830+-- if it succeeds, the result is returned. However, if the first parser fails,
831+-- the parser driver backtracks and tries the same input on the second parser,
832+-- returning the result if it succeeds.
842833--
843834-- Note: This implementation is not lazy in the second argument. The following
844835-- will fail:
@@ -846,10 +837,9 @@ data AltParseState sl sr = AltParseL !Int !sl | AltParseR !sr
846837-- >> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
847838-- *** Exception: Prelude.undefined
848839--
849−-- Compare with ParserK 'Alternative' instance method '<|>'. This
850−-- implementation allows stream fusion but has quadratic complexity. This can
851−-- fuse with other operations and can be much faster than 'Alternative'
852−-- instance for small number (less than 8) of alternatives.
840+-- Although this implementation allows stream fusion, it has quadratic
841+-- complexity, making it suitable only for a small number of compositions.
842+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
853843--
854844-- /Time Complexity:/ O(n^2) where n is the number of compositions.
855845--
@@ -1179,7 +1169,10 @@ dieM err = Parser undefined (IError <$> err) undefined
11791169-- Note: With the direct style parser type, the list in "some" and "many" is
11801170-- accumulated strictly, it cannot be consumed lazily.
11811171
1182−-- | 'Alternative' instance using 'alt'.
1172+-- | Sequential alternative. The input is first passed to the first parser, and
1173+-- if it succeeds, the result is returned. However, if the first parser fails,
1174+-- the parser driver backtracks and tries the same input on the second parser,
1175+-- returning the result if it succeeds.
11831176--
11841177-- Note: The implementation of '<|>' is not lazy in the second
11851178-- argument. The following code will fail:
@@ -1188,6 +1181,11 @@ dieM err = Parser undefined (IError <$> err) undefined
11881181-- *** Exception: Prelude.undefined
11891182-- ...
11901183--
1184+-- WARNING! this is not suitable for large scale use. As a thumb rule stream
1185+-- fusion works well for less than 8 compositions of this operation, otherwise
1186+-- consider using 'ParserK'. Do not use recursive parser implementations based
1187+-- on this Alternative instance.
1188+
11911189instance Monad m => Alternative (Parser a m) where
11921190 {-# INLINE empty #-}
11931191 empty = die "empty"
@@ -1351,6 +1349,10 @@ noErrorUnsafeConcatMap func (Parser stepL initialL extractL) =
13511349
13521350-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
13531351--
1352+-- Although this implementation allows stream fusion, it has quadratic
1353+-- complexity, making it suitable only for a small number of compositions. As a
1354+-- thumb rule use it for less than 8 compositions, use 'ParserK' otherwise.
1355+--
13541356instance Monad m => Monad (Parser a m) where
13551357 {-# INLINE return #-}
13561358 return = pure
@@ -1365,6 +1367,7 @@ instance Monad m => Fail.MonadFail (Parser a m) where
13651367 {-# INLINE fail #-}
13661368 fail = die
13671369
1370+{-
13681371-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
13691372--
13701373instance Monad m => MonadPlus (Parser a m) where
@@ -1373,6 +1376,7 @@ instance Monad m => MonadPlus (Parser a m) where
13731376
13741377 {-# INLINE mplus #-}
13751378 mplus = alt
1379+-}
13761380
13771381instance (Monad m, MonadIO m) => MonadIO (Parser a m) where
13781382 {-# INLINE liftIO #-}