unfoldl -package:massiv

unfoldl f x is equivalent to reverse (unfoldr (fmap swap . f) x).
unfoldl f x is equivalent to reverse (unfoldr (fmap swap . f) x).
Linear variant of unfold. Note how they are implemented exactly identically. They could be merged if multiplicity polymorphism was supported.
Construct a Moore machine from a state valuation and transition function
To eveluate function repeatedly to construct a list of type LengthR n a. The function recieve a state and return a new state and an element value.
>>> :set -XDataKinds

>>> unfoldl (\n -> (n + 1, 2 * n)) 0 :: LengthR 5 Integer
((((NilR :+ 8) :+ 6) :+ 4) :+ 2) :+ 0
A projection on data, which only knows how to execute a strict left-fold. It is a monad and a monoid, and is very useful for efficiently aggregating the projections on data intended for left-folding, since its concatenation (<>) has complexity of O(1).
  • Intuition
The intuition for this abstraction can be derived from lists. Let's consider the foldl' function for lists:
foldl' :: (b -> a -> b) -> b -> [a] -> b
If we rearrange its parameters we get
foldl' :: [a] -> (b -> a -> b) -> b -> b
Which in Haskell is essentially the same as
foldl' :: [a] -> (forall b. (b -> a -> b) -> b -> b)
We can isolate that part into an abstraction:
newtype Unfoldl a = Unfoldl (forall b. (b -> a -> b) -> b -> b)
Then we get to this simple morphism:
list :: [a] -> Unfoldl a
list list = Unfoldl (\ step init -> foldl' step init list)
We can do the same with say Data.Text.Text:
text :: Text -> Unfoldl Char
text text = Unfoldl (\ step init -> Data.Text.foldl' step init text)
And then we can use those both to concatenate with just an O(1) cost:
abcdef :: Unfoldl Char
abcdef = list ['a', 'b', 'c'] <> text "def"
Please notice that up until this moment no actual data materialization has happened and hence no traversals have appeared. All that we've done is just composed a function, which only specifies which parts of data structures to traverse to perform a left-fold. Only at the moment where the actual folding will happen will we actually traverse the source data. E.g., using the "fold" function:
abcdefLength :: Int
abcdefLength = fold Control.Foldl.length abcdef
Stream associations actively. Amongst other features this function provides an interface to folding.
Stream the associations actively. Amongst other features this function provides an interface to folding.
Stream associations actively. Amongst other features this function provides an interface to folding.
Stream values by a key actively.
Stream keys actively.
Stream the elements actively. Amongst other features this function provides an interface to folding.
unfold lexer into a function that returns a stream of (state, token)
Unlift a monadic unfold
Construct a strict Moore machine from a state valuation and transition function
It is like unfoldl. But it use monad as an argument instead of function.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> count = readIORef r >>= \n -> n <$ writeIORef r (n + 1)

>>> unfoldlM count :: IO (LengthR 5 Integer)
((((NilR :+ 5) :+ 4) :+ 3) :+ 2) :+ 1
It is like unfoldlM. But it has already prepared values.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> count = readIORef r >>= \n -> n <$ writeIORef r (n + 1)

>>> unfoldlMWithBase count (NilR :++ 123 :+ 456) :: IO (LengthR 5 Integer)
((((NilR :+ 3) :+ 2) :+ 1) :+ 123) :+ 456
It is like unfoldl. But it has already prepared values.
>>> :set -XDataKinds

>>> xs = NilR :++ 123 :+ 456 :: RangeR 1 5 Integer

>>> unfoldlWithBase (\n -> (n + 1, 2 * n)) 0 xs :: LengthR 5 Integer
((((NilR :+ 4) :+ 2) :+ 0) :+ 123) :+ 456
It is like unfoldlMax. But it uses a monad instead of function.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1)

>>> unfoldlMMax count :: IO (RangeR 3 5 Integer)
((((NilR :++ 15) :++ 12) :+ 9) :+ 6) :+ 3
It is like unfoldlMax. But it uses a monad instead of a function.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1)

>>> unfoldlMMin count :: IO (RangeR 3 5 Integer)
((NilR :+ 9) :+ 6) :+ 3
It is like unfoldlRange. But it use a monad instead of a function.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1)

>>> unfoldlMRange ((< 5) <$> readIORef r) count :: IO (RangeR 3 5 Integer)
(((NilR :++ 12) :+ 9) :+ 6) :+ 3
It is like unfoldlRangeMaybe. But it use a monad instead of a function. The first argument monad returns a boolean value. It creates values while this boolean value is True. If this boolean value is False before to create enough values or True after to create full values, then unfoldlMRangeMaybe returns Nothing.
>>> :set -XDataKinds

>>> :module + Data.IORef

>>> r <- newIORef 1

>>> check n0 = (< n0) <$> readIORef r

>>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1)

>>> unfoldlMRangeMaybe (check 2) count :: IO (Maybe (RangeR 3 5 Integer))
Nothing
>>> writeIORef r 1

>>> unfoldlMRangeMaybe (check 5) count :: IO (Maybe (RangeR 3 5 Integer))
Just ((((NilR :++ 12) :+ 9) :+ 6) :+ 3)
>>> writeIORef r 1

>>> unfoldlMRangeMaybe (check 10) count :: IO (Maybe (RangeR 3 5 Integer))
Nothing