>>> sepBy p1 p2 f = Parser.deintercalate p1 p2 (Fold.catLefts f) >>> sepBy p1 p2 f = Parser.sepBy1 p1 p2 f <|> Parser.fromEffect (Fold.finalM f)Examples:
>>> p1 = Parser.takeWhile1 (not . (== '+')) Fold.toList >>> p2 = Parser.satisfy (== '+') >>> p = Parser.sepBy p1 p2 Fold.toList >>> Stream.parse p $ Stream.fromList "" Right [] >>> Stream.parse p $ Stream.fromList "1" Right ["1"] >>> Stream.parse p $ Stream.fromList "1+" Right ["1"] >>> Stream.parse p $ Stream.fromList "1+2+3" Right ["1","2","3"]
>>> sepBy1 p1 p2 f = Parser.deintercalate1 p1 p2 (Fold.catLefts f)Examples:
>>> p1 = Parser.takeWhile1 (not . (== '+')) Fold.toList >>> p2 = Parser.satisfy (== '+') >>> p = Parser.sepBy1 p1 p2 Fold.toList >>> Stream.parsePos p $ Stream.fromList "" Left (ParseErrorPos 0 "takeWhile1: end of input") >>> Stream.parse p $ Stream.fromList "1" Right ["1"] >>> Stream.parse p $ Stream.fromList "1+" Right ["1"] >>> Stream.parse p $ Stream.fromList "1+2+3" Right ["1","2","3"]
>>> splitSepBy p xs = Stream.fold Fold.toList $ Stream.splitSepBySeq_ (Array.fromList p) Fold.toList (Stream.fromList xs)
>>> splitSepBy "" "" []
>>> splitSepBy "" "a...b" ["a",".",".",".","b"]
>>> splitSepBy ".." "" []
>>> splitSepBy ".." "a...b" ["a",".b"]
>>> splitSepBy ".." "abc" ["abc"]
>>> splitSepBy ".." ".." ["",""]
>>> splitSepBy "." ".a" ["","a"]
>>> splitSepBy "." "a." ["a",""]Uses Rabin-Karp algorithm for substring search.
>>> splitOn p xs = Stream.fold Fold.toList $ Stream.splitSepBy_ p Fold.toList (Stream.fromList xs) >>> splitOn (== '.') "a.b" ["a","b"]Splitting an empty stream results in an empty stream i.e. zero splits:
>>> splitOn (== '.') "" []If the stream does not contain the separator then it results in a single split:
>>> splitOn (== '.') "abc" ["abc"]If one or both sides of the separator are missing then the empty segment on that side is folded to the default output of the fold:
>>> splitOn (== '.') "." ["",""]
>>> splitOn (== '.') ".a" ["","a"]
>>> splitOn (== '.') "a." ["a",""]
>>> splitOn (== '.') "a..b" ["a","","b"]splitSepBy_ is an inverse of unfoldEachSepBy:
Stream.unfoldEachSepBy '.' Unfold.fromList . Stream.splitSepBy_ (== '.') Fold.toList === idAssuming the input stream does not contain the separator:
Stream.splitSepBy_ (== '.') Fold.toList . Stream.unfoldEachSepBy '.' Unfold.fromList === id
>>> unfoldEachSepBySeq a u = Stream.unfoldEach u . Stream.intersperse a >>> unfoldEachSepBySeq a u = Stream.intercalateSepBy u (Stream.repeat a) uIdioms:
>>> intersperse x = Stream.unfoldEachSepBySeq x Unfold.identity >>> unwords = Stream.unfoldEachSepBySeq " " Unfold.fromListUsage:
>>> input = Stream.fromList ["abc", "def", "ghi"] >>> Stream.toList $ Stream.unfoldEachSepBySeq " " Unfold.fromList input "abc def ghi"
>>> concatSepBy x = Stream.unfoldEachSepBy x Array.reader
>>> intercalateSepBy u1 s1 u2 s2 = Stream.concat $ Stream.interleaveSepBy (fmap (Stream.unfold u1) s1) (fmap (Stream.unfold u2) s2)If the separator stream consists of nil streams then it becomes equivalent to unfoldEach:
>>> unfoldEach = Stream.intercalateSepBy (Unfold.nilM (const (return ()))) (Stream.repeat ())Pre-release
(. . .) (a b c) => a . b . c -- additional . is discarded (. . ) (a b c) => a . b . c (. ) (a b c) => a . b c -- missing . is ignoredExamples:
>>> f x y = Stream.toList $ Stream.interleaveSepBy (Stream.fromList x) (Stream.fromList y) >>> f "..." "abc" "a.b.c" >>> f ".." "abc" "a.b.c" >>> f "." "abc" "a.bc"
(. . .) (a b c) => a . b . c -- additional . is discarded (. . ) (a b c) => a . b . c (. ) (a b c) => a . b -- c is discarded
>>> f x y = Stream.toList $ Stream.interleaveSepBy' (Stream.fromList x) (Stream.fromList y) >>> f "..." "abc" "a.b.c" >>> f ".." "abc" "a.b.c" >>> f "." "abc" "a.b"
>>> unfoldEachSepBy x = Stream.unfoldEachSepByM (return x) >>> unfoldEachSepBy x = Stream.intercalateSepBy Unfold.identity (Stream.repeat x)Usage:
>>> unwords = Stream.unfoldEachSepBy ' 'Pre-release
>>> unfoldEachSepByM x = Stream.intercalateSepBy Unfold.identity (Stream.repeatM x)