{
  "$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"
}