on master help sign in
Update parser docs, disable MonadPlus instance
5d28f70Harendra Kumar
core/src/Streamly/Internal/Data/Parser/ParserD.hs+2−1
@@ -380,7 +380,8 @@ toFold (Parser pstep pinitial pextract) = Fold step initial extract
380-- Upgrade folds to parses
380-- Upgrade folds to parses
381-------------------------------------------------------------------------------
381-------------------------------------------------------------------------------
382
382
383−-- | Make a 'Parser' from a 'Fold'.
383+-- | Make a 'Parser' from a 'Fold'. This parser sends all of its input to the
384+-- fold.
384--
385--
385{-# INLINE fromFold #-}
386{-# INLINE fromFold #-}
386fromFold :: Monad m => Fold m a b -> Parser a m b
387fromFold :: Monad m => Fold m a b -> Parser a m b
core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs+46−42
@@ -203,7 +203,8 @@ where
203
203
204import Control.Applicative (Alternative(..), liftA2)
204import Control.Applicative (Alternative(..), liftA2)
205import Control.Exception (Exception(..))
205import Control.Exception (Exception(..))
206−import Control.Monad (MonadPlus(..), (>=>))
206+-- import Control.Monad (MonadPlus(..), (>=>))
207+import Control.Monad ((>=>))
207import Control.Monad.IO.Class (MonadIO, liftIO)
208import Control.Monad.IO.Class (MonadIO, liftIO)
208import Data.Bifunctor (Bifunctor(..))
209import Data.Bifunctor (Bifunctor(..))
209import Fusion.Plugin.Types (Fuse(..))
210import Fusion.Plugin.Types (Fuse(..))
@@ -218,7 +219,9 @@ import Prelude hiding (concatMap, filter)
218-- >>> :m
219-- >>> :m
219-- >>> import Control.Applicative ((<|>))
220-- >>> import Control.Applicative ((<|>))
220-- >>> import Data.Bifunctor (second)
221-- >>> 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)
222-- >>> import qualified Streamly.Data.Fold as Fold
225-- >>> import qualified Streamly.Data.Fold as Fold
223-- >>> import qualified Streamly.Data.Stream as Stream
226-- >>> import qualified Streamly.Data.Stream as Stream
224-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse)
227-- >>> import qualified Streamly.Internal.Data.Stream as Stream (parse)
@@ -492,16 +495,17 @@ data SeqParseState sl f sr = SeqParseL !sl | SeqParseR !f !sr
492-- cannot scale to a large number of compositions. After around 100
495-- cannot scale to a large number of compositions. After around 100
493-- compositions the performance starts dipping rapidly beyond a CPS style
496-- compositions the performance starts dipping rapidly beyond a CPS style
494-- unfused implementation.
497-- 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.
501--
498--
502-- Note: This is a parsing dual of appending streams using
499-- Note: This is a parsing dual of appending streams using
503−-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and zips
500+-- 'Streamly.Data.Stream.append', it splits the streams using two parsers and
504−-- the results.
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.
505--
509--
506-- This implementation is strict in the second argument, therefore, the
510-- This implementation is strict in the second argument, therefore, the
507-- following will fail:
511-- following will fail:
@@ -510,28 +514,15 @@ data SeqParseState sl f sr = SeqParseL !sl | SeqParseR !f !sr
510-- *** Exception: Prelude.undefined
514-- *** Exception: Prelude.undefined
511-- ...
515-- ...
512--
516--
513−-- Compare with 'Applicative' instance method '<*>'. This implementation allows
514−-- stream fusion but has quadratic complexity. This can fuse with other
517+-- Although this implementation allows stream fusion, it has quadratic
515−-- operations and can be faster than 'Applicative' instance for small number
518+-- complexity, making it suitable only for a small number of compositions.
516−-- (less than 8) of compositions.
519+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
517−--
518−-- Many combinators can be expressed using @splitWith@ and other parser
519−-- primitives. Some common idioms are described below,
520--
520--
521−-- @
521+-- Below are some common idioms that can be expressed using 'splitWith' and
522−-- span :: (a -> Bool) -> Fold m a b -> Fold m a b -> Parser a m b
522+-- other parser primitives:
523−-- span pred f1 f2 = splitWith (,) ('takeWhile' pred f1) ('fromFold' f2)
524−-- @
525--
523--
526−-- @
524+-- >>> span p f1 f2 = Parser.splitWith (,) (Parser.takeWhile p f1) (Parser.fromFold f2)
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)
525+-- >>> spanBy eq f1 f2 = Parser.splitWith (,) (Parser.groupBy eq f1) (Parser.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−-- @
535--
526--
536-- /Pre-release/
527-- /Pre-release/
537--
528--
@@ -695,10 +686,9 @@ data SeqAState sl sr = SeqAL !sl | SeqAR !sr
695-- *** Exception: Prelude.undefined
686-- *** Exception: Prelude.undefined
696-- ...
687-- ...
697--
688--
698−-- Compare with 'Applicative' instance method '*>'. This implementation allows
699−-- stream fusion but has quadratic complexity. This can fuse with other
689+-- Although this implementation allows stream fusion, it has quadratic
700−-- operations, and can be faster than 'Applicative' instance for small
690+-- complexity, making it suitable only for a small number of compositions.
701−-- number (less than 8) of compositions.
691+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
702--
692--
703-- /Pre-release/
693-- /Pre-release/
704--
694--
@@ -836,9 +826,10 @@ data AltParseState sl sr = AltParseL !Int !sl | AltParseR !sr
836-- each subsequent alternative's input element has to go through, therefore, it
826-- each subsequent alternative's input element has to go through, therefore, it
837-- cannot scale to a large number of compositions
827-- cannot scale to a large number of compositions
838
828
839−-- | Sequential alternative. Apply the input to the first parser and return the
829+-- | Sequential alternative. The input is first passed to the first parser, and
840−-- result if the parser succeeds. If the first parser fails then backtrack and
830+-- if it succeeds, the result is returned. However, if the first parser fails,
841−-- apply the same input to the second parser and return the result.
831+-- the parser driver backtracks and tries the same input on the second parser,
832+-- returning the result if it succeeds.
842--
833--
843-- Note: This implementation is not lazy in the second argument. The following
834-- Note: This implementation is not lazy in the second argument. The following
844-- will fail:
835-- will fail:
@@ -846,10 +837,9 @@ data AltParseState sl sr = AltParseL !Int !sl | AltParseR !sr
846-- >> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
837-- >> Stream.parse (Parser.satisfy (> 0) `Parser.alt` undefined) $ Stream.fromList [1..10]
847-- *** Exception: Prelude.undefined
838-- *** Exception: Prelude.undefined
848--
839--
849−-- Compare with ParserK 'Alternative' instance method '<|>'. This
850−-- implementation allows stream fusion but has quadratic complexity. This can
840+-- Although this implementation allows stream fusion, it has quadratic
851−-- fuse with other operations and can be much faster than 'Alternative'
841+-- complexity, making it suitable only for a small number of compositions.
852−-- instance for small number (less than 8) of alternatives.
842+-- As a thumb rule use it for less than 8 compositions, use ParserK otherwise.
853--
843--
854-- /Time Complexity:/ O(n^2) where n is the number of compositions.
844-- /Time Complexity:/ O(n^2) where n is the number of compositions.
855--
845--
@@ -1179,7 +1169,10 @@ dieM err = Parser undefined (IError <$> err) undefined
1179-- Note: With the direct style parser type, the list in "some" and "many" is
1169-- Note: With the direct style parser type, the list in "some" and "many" is
1180-- accumulated strictly, it cannot be consumed lazily.
1170-- accumulated strictly, it cannot be consumed lazily.
1181
1171
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.
1183--
1176--
1184-- Note: The implementation of '<|>' is not lazy in the second
1177-- Note: The implementation of '<|>' is not lazy in the second
1185-- argument. The following code will fail:
1178-- argument. The following code will fail:
@@ -1188,6 +1181,11 @@ dieM err = Parser undefined (IError <$> err) undefined
1188-- *** Exception: Prelude.undefined
1181-- *** Exception: Prelude.undefined
1189-- ...
1182-- ...
1190--
1183--
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+
1191instance Monad m => Alternative (Parser a m) where
1189instance Monad m => Alternative (Parser a m) where
1192 {-# INLINE empty #-}
1190 {-# INLINE empty #-}
1193 empty = die "empty"
1191 empty = die "empty"
@@ -1351,6 +1349,10 @@ noErrorUnsafeConcatMap func (Parser stepL initialL extractL) =
1351
1349
1352-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
1350-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
1353--
1351--
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+--
1354instance Monad m => Monad (Parser a m) where
1356instance Monad m => Monad (Parser a m) where
1355 {-# INLINE return #-}
1357 {-# INLINE return #-}
1356 return = pure
1358 return = pure
@@ -1365,6 +1367,7 @@ instance Monad m => Fail.MonadFail (Parser a m) where
1365 {-# INLINE fail #-}
1367 {-# INLINE fail #-}
1366 fail = die
1368 fail = die
1367
1369
1370+{-
1368-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
1371-- | See documentation of 'Streamly.Internal.Data.Parser.ParserK.Type.Parser'.
1369--
1372--
1370instance Monad m => MonadPlus (Parser a m) where
1373instance Monad m => MonadPlus (Parser a m) where
@@ -1373,6 +1376,7 @@ instance Monad m => MonadPlus (Parser a m) where
1373
1376
1374 {-# INLINE mplus #-}
1377 {-# INLINE mplus #-}
1375 mplus = alt
1378 mplus = alt
1379+-}
1376
1380
1377instance (Monad m, MonadIO m) => MonadIO (Parser a m) where
1381instance (Monad m, MonadIO m) => MonadIO (Parser a m) where
1378 {-# INLINE liftIO #-}
1382 {-# INLINE liftIO #-}
core/src/Streamly/Internal/Data/Stream/StreamK.hs+4
@@ -1280,6 +1280,10 @@ parserDone :: Applicative m =>
1280parserDone (ParserK.Success n b) _ _ = pure $ ParserK.Done n b
1280parserDone (ParserK.Success n b) _ _ = pure $ ParserK.Done n b
1281parserDone (ParserK.Failure n e) _ _ = pure $ ParserK.Error n e
1281parserDone (ParserK.Failure n e) _ _ = pure $ ParserK.Error n e
1282
1282
1283+-- XXX parseDBreakChunks may be faster than converting parserD to parserK and
1284+-- using parseBreakChunks. We can also use parseBreak as an alternative to the
1285+-- monad instance of ParserD.
1286+
1283-- | Run a 'ParserK' over a chunked 'StreamK' and return the rest of the Stream.
1287-- | Run a 'ParserK' over a chunked 'StreamK' and return the rest of the Stream.
1284{-# INLINE_NORMAL parseBreakChunks #-}
1288{-# INLINE_NORMAL parseBreakChunks #-}
1285parseBreakChunks
1289parseBreakChunks