{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreidvqta5edlebanzwu7oclmcnysw6jxyvoep55k5fvgiskmeeav5su",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mkuzxypnrcp2"
  },
  "path": "/t/conduit-to-yield-first-lines-from-file-without-leaking-space-or-file-handles/14030#post_8",
  "publishedAt": "2026-05-02T14:33:53.000Z",
  "site": "https://discourse.haskell.org",
  "tags": [
    "jet-stream",
    "Jet type",
    "Bluefin streams"
  ],
  "textContent": "danidiaz:\n\n> my own toy library jet-stream\n\nNice! Your Jet type is isomorphic to a special case of Bluefin streaming. Let’s see how.\n\nWe have\n\n\n    newtype Jet a = Jet\n      { runJet :: forall s. (s -> Bool) -> (s -> a -> IO s) -> s -> IO s\n      }\n\n\nwhich is\n\n\n    StateT s IO Bool -> (a -> StateT s IO ()) -> StateT s IO ()\n\n\n(modulo the fact that the `stop` callback can’t modify the state). Now, I’m pretty sure that we could instead use\n\n\n    (a -> IO ()) -> IO ()\n\n\n  1. The `StateT s` part of this could be equivalently done by having an `IORef` in the closure of an `IO` higher order function\n  2. Then the `stop` callback functionality could be handled by a useful combinator `until :: IO Bool -> Jet a -> Jet a`\n\n\n\nIf I’m right then this is a special case of Bluefin streams which are implemented under the hood as `(a -> IO ()) -> IO ()`.\n\nI’m pretty sure what you call “continuation-based” streaming libraries are the right way to go.",
  "title": "Conduit to yield first lines from file without leaking space or file handles?"
}