>>> :set -XDataKinds >>> unfoldl (\n -> (n + 1, 2 * n)) 0 :: LengthR 5 Integer ((((NilR :+ 8) :+ 6) :+ 4) :+ 2) :+ 0
foldl' :: (b -> a -> b) -> b -> [a] -> bIf we rearrange its parameters we get
foldl' :: [a] -> (b -> a -> b) -> b -> bWhich 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
>>> import Data.Massiv.Array >>> unfoldlPrimM_ (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return ((f1, fn), f0)) (0, 1) :: IO (Array P Ix1 Int) (0,1) (1,1) (1,2) (2,3) (3,5) (5,8) (8,13) (13,21) (21,34) (34,55) Array P Seq (Sz1 10) [ 34, 21, 13, 8, 5, 3, 2, 1, 1, 0 ]
>>> :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
>>> :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
>>> :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
>>> :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
>>> :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
>>> :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
>>> :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
>>> :set -XDataKinds >>> :module + Data.IORef >>> r <- newIORef 1 >>> check = (< 3) <$> readIORef r >>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1) >>> xs = NilR :++ 123 :+ 456 :: RangeR 1 5 Integer >>> :{ unfoldlMRangeMaybeWithBase check count xs :: IO (Maybe (RangeR 3 5 Integer)) :} Just ((((NilR :++ 6) :+ 3) :+ 123) :+ 456)
>>> :set -XDataKinds >>> :module + Data.IORef >>> r <- newIORef 1 >>> count = readIORef r >>= \n -> n * 3 <$ writeIORef r (n + 1) >>> xs = NilR :++ 123 :+ 456 :: RangeR 1 5 Integer >>> :{ unfoldlMRangeWithBase ((< 3) <$> readIORef r) count xs :: IO (RangeR 3 5 Integer) :} (((NilR :++ 6) :+ 3) :+ 123) :+ 456
>>> :set -XDataKinds >>> unfoldlMax (\n -> (n + 1, n * 3)) 1 :: RangeR 3 5 Integer ((((NilR :++ 15) :++ 12) :+ 9) :+ 6) :+ 3