@@ -16,6 +16,9 @@
16-- stream fusion. If strings are to be stored or buffered in memory, they can
16-- stream fusion. If strings are to be stored or buffered in memory, they can
17-- be encoded to 'Word8' arrays using the encoding routines provided in the
17-- be encoded to 'Word8' arrays using the encoding routines provided in the
18-- module. Therefore, a separate type for text representation is not required.
18-- 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.
20-- The 'String' type in this module is just a synonym for the type @List Char@.
23-- The 'String' type in this module is just a synonym for the type @List Char@.
21-- It provides better performance compared to the standard Haskell @String@
24-- It provides better performance compared to the standard Haskell @String@
@@ -49,6 +52,7 @@ module Streamly.String
49 -- * Operations on character strings
52 -- * Operations on character strings
50 , strip -- (dropAround isSpace)
53 , strip -- (dropAround isSpace)
51 , stripEnd-}
54 , stripEnd-}
52 , stripStart
56 , stripStart
53 , foldLines
57 , foldLines
54 , foldWords
58 , foldWords
@@ -153,14 +157,27 @@ stripEnd :: IsStream t => t m Char -> t m Char
153stripEnd = undefined
157stripEnd = undefined
160+-- | Remove leading whitespace from a String.
162+-- > stripStart = S.dropWhile isSpace
156{-# INLINE stripStart #-}
163{-# INLINE stripStart #-}
157stripStart :: (Monad m, IsStream t) => t m Char -> t m Char
164stripStart :: (Monad m, IsStream t) => t m Char -> t m Char
158stripStart = S.dropWhile isSpace
165stripStart = S.dropWhile isSpace
167+-- | Fold each line of the stream using the supplied Fold
168+-- and stream the result.
170+-- >>> S.toList $ foldLines (S.fromList "lines\nthis\nstring\n\n\n") FL.toList
171+-- ["lines", "this", "string", "", ""]
160{-# INLINE foldLines #-}
172{-# INLINE foldLines #-}
161foldLines :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
173foldLines :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
162foldLines = flip (FL.splitSuffixBy (== '\n'))
174foldLines = flip (FL.splitSuffixBy (== '\n'))
176+-- | Fold each word of the stream using the supplied Fold
177+-- and stream the result.
179+-- >>> S.toList $ foldWords (S.fromList "fold these words") FL.toList
180+-- ["fold", "these", "words"]
164{-# INLINE foldWords #-}
181{-# INLINE foldWords #-}
165foldWords :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
182foldWords :: (Monad m, IsStream t) => t m Char -> Fold m Char b -> t m b
166foldWords = flip (FL.wordsBy isSpace)
183foldWords = flip (FL.wordsBy isSpace)
@@ -168,7 +185,7 @@ foldWords = flip (FL.wordsBy isSpace)
168foreign import ccall unsafe "u_iswspace"
185foreign import ccall unsafe "u_iswspace"
169 iswspace :: Int -> Int
186 iswspace :: Int -> Int
171−-- Code copied from base/Data.Char to INLINE it
188+-- | Code copied from base/Data.Char to INLINE it
172{-# INLINE isSpace #-}
189{-# INLINE isSpace #-}
173isSpace :: Char -> Bool
190isSpace :: Char -> Bool
@@ -177,18 +194,56 @@ isSpace c
178 uc = fromIntegral (ord c) :: Word
195 uc = fromIntegral (ord c) :: Word
197+-- | Break a string up into a list of strings at newline characters.
198+-- The resulting strings do not contain newlines.
200+-- >>> S.toList $ lines $ S.fromList "lines\nthis\nstring\n\n\n"
201+-- ["lines","this","string","",""]
203+-- If you're dealing with lines of massive length, consider using
204+-- 'foldLines' instead.
180{-# INLINE lines #-}
205{-# INLINE lines #-}
181lines :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
206lines :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
182lines = FL.splitSuffixBy (== '\n') toArray
207lines = FL.splitSuffixBy (== '\n') toArray
209+-- | Break a string up into a list of strings, which were delimited
210+-- by characters representing white space.
212+-- >>> S.toList $ words $ S.fromList "A newline\nis considered white space?"
213+-- ["A", "newline", "is", "considered", "white", "space?"]
215+-- If you're dealing with words of massive length, consider using
216+-- 'foldWords' instead.
184{-# INLINE words #-}
217{-# INLINE words #-}
185words :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
218words :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
186words = FL.wordsBy isSpace toArray
219words = FL.wordsBy isSpace toArray
221+-- | Flattens the stream of @Array Char@, after appending a terminating
222+-- newline to each string.
224+-- 'unlines' is an inverse operation to 'lines'.
226+-- >>> S.toList $ unlines $ S.fromList ["lines", "this", "string"]
227+-- "lines\nthis\nstring\n"
229+-- Note that, in general
231+-- > unlines . lines /= id
188{-# INLINE unlines #-}
232{-# INLINE unlines #-}
189unlines :: (MonadIO m, IsStream t) => t m (Array Char) -> t m Char
233unlines :: (MonadIO m, IsStream t) => t m (Array Char) -> t m Char
190unlines = D.fromStreamD . A.unlines '\n' . D.toStreamD
234unlines = D.fromStreamD . A.unlines '\n' . D.toStreamD
236+-- | Flattens the stream of @Array Char@, after appending a separating
237+-- space to each string.
239+-- 'unwords' is an inverse operation to 'words'.
241+-- >>> S.toList $ unwords $ S.fromList ["unwords", "this", "string"]
242+-- "unwords this string"
244+-- Note that, in general
246+-- > unwords . words /= id
192{-# INLINE unwords #-}
247{-# INLINE unwords #-}
193unwords :: (MonadAsync m, IsStream t) => t m (Array Char) -> t m Char
248unwords :: (MonadAsync m, IsStream t) => t m (Array Char) -> t m Char
194unwords = A.flattenArrays . (S.intersperse (A.fromList " "))
249unwords = A.flattenArrays . (S.intersperse (A.fromList " "))