{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreibkdae6phqowayu2zwjbsvj5txbvmqutafpc5zrmprktsidyoxsca",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mmqkak5kive2"
},
"path": "/t/lazily-consuming-a-self-referential-linked-list/14131#post_18",
"publishedAt": "2026-05-26T05:02:13.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"project"
],
"textContent": "As promised here’s an application of recursion schemes to your problem. What you are in fact doing is what appears to be a `hylomorphism`. After looking through your type classes it appears you are trying to construct containers that have list-like semantics. That is they can be unfolded and folded over. In fact your call to `Foldable.toList` is actually a catamorphism and can be fused with the hylomorphism. Unfortunately I don’t have time to dive deeper into the theory here, but I believe your library is a wrapper around these concepts. I would take a deeper look into the `ListF` data type and learn about cata-, ana-, and hylomorphisms (and maybe futu-). But nonetheless here’s a small something I came up with:\n\n\n import Data.Functor.Foldable (ListF (..), hylo, project)\n import Control.Monad (join)\n import Data.Foldable (toList)\n import Control.Category ((>>>))\n\n data GoF m a\n = Done\n | Rec (m a)\n deriving (Functor)\n\n newtype WorkListT t q m a = WorkListT (t -> m (q t, a))\n\n -- | Execute the provided monadic action until the task queue is exhausted.\n --\n -- Will diverge if the task queue is infinite, unless the base monad allows\n -- for an early exit, like t'Control.Monad.Except.ExceptT'.\n run :: (Foldable f, Monad m) => f t -> WorkListT t [] m () -> m ()\n run fQueue (WorkListT f) = hylo runGoF (go' project f) . toList $ fQueue\n\n runGoF :: (Monad m) => GoF m (m ()) -> m ()\n runGoF = \\case\n Done -> pure ()\n Rec x -> join x\n\n -- Maybe (e, a) ~ ListF e a\n go' :: (Functor m, Semigroup (q a)) => (q a -> ListF a (q a)) -> (a -> m (q a, b)) -> q a -> GoF m (q a)\n go' snoc f = snoc >>> \\case\n Nil -> Done\n Cons a as -> Rec $ ((as <>) . fst) <$> f a\n\n\nNote that `go'` is a co-algebra “constructor” that is given a way to project from a list, and a `WorkListT` construct a co-algebra where your `q a` is the seed and `GoF` is the shape of your recursion.\n\nFinal thought, I believe you can fuse the `hylo` and `toList` together but I’ll leave this an exercise.",
"title": "Lazily consuming a self-referential linked list"
}