foldl' :: (a -> Fiber -> a) -> a -> Yarn -> IO a
foldl' f z y = do
    seekable <- IO.hIsSeekable $ unYarn y
    when seekable $
        IO.hSeek h IO.AbsoluteSeek 0
    loop id z
  where
    loop front x = do  -- more bytes are needed
        eof <- IO.hIsEOF h
        if eof
            then finish front x
            else do
                buf <- BS.hGet h 4096
                go front buf x
    go front more x = do  -- 'more' is always the beginning of a line
        let (first, second) = BS.break (== '\n') more
        case BS.uncons second of
            Nothing -> loop (BS.append $ front more) x
            Just (_, second') -> do
                let l = front first
                if BS.null l
                    then fail "Yarn.foldl: an empty line"
                    else do
                        let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                        let !x' = f x fib
                        go id second' x'
    finish front x = do
        let l = front BS.empty
        if BS.null l
            then return x
            else do
                let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                let !x' = f x fib
                return x'
    !h = unYarn y
foldl' :: (a -> Fiber -> a) -> a -> Yarn -> IO a
foldl' f z y = do
    seekable <- IO.hIsSeekable $ unYarn y
    when seekable $
        IO.hSeek h IO.AbsoluteSeek 0
    loop id z
  where
    loop front x = do  -- more bytes are needed
        eof <- IO.hIsEOF h
        if eof
            then finish front x
            else do
                buf <- BS.hGet h 4096
                go front buf x
    go front more x = do  -- 'more' is always the beginning of a line
        let (first, second) = BS.break (== '\n') more
        case BS.uncons second of
            Nothing -> loop (BS.append $ front more) x
            Just (_, second') -> do
                let l = front first
                if BS.null l
                    then fail "Yarn.foldl: an empty line"
                    else do
                        let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                        let !x' = f x fib
                        go id second' x'
    finish front x = do
        let l = front BS.empty
        if BS.null l
            then return x
            else do
                let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                let !x' = f x fib
                return x'
    !h = unYarn y
foldl' f z y = do
    seekable <- IO.hIsSeekable $ unYarn y
    when seekable $
        IO.hSeek h IO.AbsoluteSeek 0
    loop id z
  where
    loop front x = do  -- more bytes are needed
        eof <- IO.hIsEOF h
        if eof
            then finish front x
            else do
                buf <- BS.hGet h 4096
                go front buf x
    go front more x = do  -- 'more' is always the beginning of a line
        let (first, second) = BS.break (== '\n') more
        case BS.uncons second of
            Nothing -> loop (BS.append $ front more) x
            Just (_, second') -> do
                let l = front first
                if BS.null l
                    then fail "Yarn.foldl: an empty line"
                    else do
                        let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                        let !x' = f x fib
                        go id second' x'
    finish front x = do
        let l = front BS.empty
        if BS.null l
            then return x
            else do
                let fib = either (error . ("Yarn.foldl: " ++)) id $ Aeson.eitherDecode $ LBS.fromStrict l
                let !x' = f x fib
                return x'
    !h = unYarn y