Lazy file reading

mdo
  line <- BS.hGetLine file
  ((parse line) :) <$> readLines file

Is equivalent to

do
  line <- BS.hGetLine file
  rest <- readLines file
  pure $ (parse line) : rest

which is

do
  line <- BS.hGetLine file
  line' <- BS.hGetLine file
  line'' <- BS.hGetLine file
  ...
  pure $ (parse line) : (parse line') : (parse line'') : ...

So it should always read the whole file and throw an EOF error since it didn’t handle that.