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