@@ -16,6 +16,9 @@
1616-- stream fusion. If strings are to be stored or buffered in memory, they can
1717-- be encoded to 'Word8' arrays using the encoding routines provided in the
1818-- module. Therefore, a separate type for text representation is not required.
19+-- A @Stream Identity Char@ can be used almost as a drop-in replacement for the
20+-- standard Haskell @String@, especially when used with @OverloadedStrings@
21+-- extension, with little differences.
1922
2023-- The 'String' type in this module is just a synonym for the type @List Char@.
2124-- It provides better performance compared to the standard Haskell @String@
@@ -49,6 +52,7 @@ module Streamly.String
4952 -- * Operations on character strings
5053 , strip -- (dropAround isSpace)
5154 , stripEnd-}
55+ -- * Substrings
5256 , stripStart
5357 , foldLines
5458 , foldWords
@@ -153,14 +157,27 @@ stripEnd :: IsStream t => t m Char -> t m Char
153157stripEnd = undefined
154158-}
155159
160+-- | Remove leading whitespace from a String.
161+--
162+-- > stripStart = S.dropWhile isSpace
156163{-# INLINE stripStart #-}
157164stripStart :: (Monad m, IsStream t) => t m Char -> t m Char
158165stripStart = S.dropWhile isSpace
159166
167+-- | Fold each line of the stream using the supplied Fold
168+-- and stream the result.
169+--
170+-- >>> S.toList $ foldLines (S.fromList "lines\nthis\nstring\n\n\n") FL.toList
171+-- ["lines", "this", "string", "", ""]
160172{-# INLINE foldLines #-}
161173foldLines :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
162174foldLines = flip (FL.splitSuffixBy (== '\n'))
163175
176+-- | Fold each word of the stream using the supplied Fold
177+-- and stream the result.
178+--
179+-- >>> S.toList $ foldWords (S.fromList "fold these words") FL.toList
180+-- ["fold", "these", "words"]
164181{-# INLINE foldWords #-}
165182foldWords :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
166183foldWords = flip (FL.wordsBy isSpace)
@@ -168,7 +185,7 @@ foldWords = flip (FL.wordsBy isSpace)
168185foreign import ccall unsafe "u_iswspace"
169186 iswspace :: Int -> Int
170187
171−-- Code copied from base/Data.Char to INLINE it
188+-- | Code copied from base/Data.Char to INLINE it
172189{-# INLINE isSpace #-}
173190isSpace :: Char -> Bool
174191isSpace c
@@ -177,18 +194,56 @@ isSpace c
177194 where
178195 uc = fromIntegral (ord c) :: Word
179196
197+-- | Break a string up into a list of strings at newline characters.
198+-- The resulting strings do not contain newlines.
199+--
200+-- >>> S.toList $ lines $ S.fromList "lines\nthis\nstring\n\n\n"
201+-- ["lines","this","string","",""]
202+--
203+-- If you're dealing with lines of massive length, consider using
204+-- 'foldLines' instead.
180205{-# INLINE lines #-}
181206lines :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
182207lines = FL.splitSuffixBy (== '\n') toArray
183208
209+-- | Break a string up into a list of strings, which were delimited
210+-- by characters representing white space.
211+--
212+-- >>> S.toList $ words $ S.fromList "A newline\nis considered white space?"
213+-- ["A", "newline", "is", "considered", "white", "space?"]
214+--
215+-- If you're dealing with words of massive length, consider using
216+-- 'foldWords' instead.
184217{-# INLINE words #-}
185218words :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
186219words = FL.wordsBy isSpace toArray
187220
221+-- | Flattens the stream of @Array Char@, after appending a terminating
222+-- newline to each string.
223+--
224+-- 'unlines' is an inverse operation to 'lines'.
225+--
226+-- >>> S.toList $ unlines $ S.fromList ["lines", "this", "string"]
227+-- "lines\nthis\nstring\n"
228+--
229+-- Note that, in general
230+--
231+-- > unlines . lines /= id
188232{-# INLINE unlines #-}
189233unlines :: (MonadIO m, IsStream t) => t m (Array Char) -> t m Char
190234unlines = D.fromStreamD . A.unlines '\n' . D.toStreamD
191235
236+-- | Flattens the stream of @Array Char@, after appending a separating
237+-- space to each string.
238+--
239+-- 'unwords' is an inverse operation to 'words'.
240+--
241+-- >>> S.toList $ unwords $ S.fromList ["unwords", "this", "string"]
242+-- "unwords this string"
243+--
244+-- Note that, in general
245+--
246+-- > unwords . words /= id
192247{-# INLINE unwords #-}
193248unwords :: (MonadAsync m, IsStream t) => t m (Array Char) -> t m Char
194249unwords = A.flattenArrays . (S.intersperse (A.fromList " "))