@@ -34,6 +34,9 @@ module Data.Text.Fusion
34 -- ** Scans
34 -- ** Scans
35 , reverseScanr
35 , reverseScanr
37+ -- ** Accumulating maps
37 -- ** Generation and unfolding
40 -- ** Generation and unfolding
38 , unfoldrN
41 , unfoldrN
@@ -199,3 +202,30 @@ findIndex = S.findIndexI
199countChar :: Char -> Stream Char -> Int
202countChar :: Char -> Stream Char -> Int
200countChar = S.countCharI
203countChar = S.countCharI
201{-# INLINE [0] countChar #-}
204{-# INLINE [0] countChar #-}
206+-- | /O(n)/ Like a combination of 'map' and 'foldl''. Applies a
207+-- function to each element of a 'Text', passing an accumulating
208+-- parameter from left to right, and returns a final 'Text'.
209+mapAccumL :: (a -> Char -> (a,Char)) -> a -> Stream Char -> (a, Text)
210+mapAccumL f z0 (Stream next0 s0 len) = (nz,I.textP na 0 nl)
212+ (na,(nz,nl)) = A.run2 (A.unsafeNew mlen >>= \arr -> outer arr mlen z0 s0 0)
213+ where mlen = upperBound 4 len
214+ outer arr top = loop
218+ Done -> return (arr, (z,i))
219+ Skip s' -> loop z s' i
221+ | j >= top -> {-# SCC "mapAccumL/resize" #-} do
222+ let top' = (top + 1) `shiftL` 1
223+ arr' <- A.unsafeNew top'
224+ A.copyM arr' 0 arr 0 top
225+ outer arr' top' z s i
226+ | otherwise -> do let (z',c) = f z x
227+ d <- unsafeWrite arr i c
229+ where j | ord x < 0x10000 = i
231+{-# INLINE [0] mapAccumL #-}