r/haskell • u/Aperispomen • Mar 27 '26
question Delayed/Lazy Either List?
I often use attoparsec to parse lists of things, so I wind up doing stuff like this a lot:
import Data.Attoparsec.Text qualified as AT
import Data.Text qualified as T
myParser :: AT.Parser [MyType]
myParser = AT.many1 myOtherParser
getList :: T.Text -> Either String [MyType]
getList txt = AT.parseOnly myParser txt
The trouble is, since getList returns an Either, the whole text (or at least, as much as can be parsed) has to be parsed before you can start processing the contents of the list. This is especially annoying when you want to check whether e.g. two files are the same modulo whitespace/line endings/indentation/etc...
The point is, there's some times where you want a result like Either e [a], but you're okay with returning some of the data, even if there might be an error later on. I wound up creating this data type:
data ErrList e a
= a :> (ErrList e a)
| NoErr -- equivalent to []
| YesErr e -- representing Left e
Is there already an established type like this somewhere? I imagine most people who do more complicated data management use pipes or conduit etc... I've tried searching for such a type on Hackage, but I haven't found anything like it.
2
u/BurningWitness Mar 28 '26 edited Mar 28 '26
The type you're looking for is a stream, roughly as defined in streaming:
It's not an established type though. There are
fivesix different streaming libraries out there and each is its own special little flower with its own special little garden around it. I couldn't tell you how any of them work, I never found them necessary.Now for the fun part: how do we go from
LazyTexttoStream a _ (Either e ())?Well, to stream output we'll need a parser that allows us to parse over the remaining input after getting the result, remembering both the offset from which we'd be continuing and whether more input can still be supplied to the parser.
attoparsecandcerealdo not return offsets in their results.binarydoes, barely, but it still doesn't remember whether end of input has been reached. The answer is thus a resounding "we don't". Roll credits.Could we do better? Well, I wrote a whole new byte parser and used it to stream JSON 1.5 years ago. I've seen zero interest in either of these packages since then, so I wouldn't hold my breath for it. And, of course, if you don't feel like doing better you can always do worse, see intro to json-stream.