+type Lens' a b = forall f . Functor f => (b -> f b) -> (a -> f a)
+
+type Codec
+ = forall m r
+ . Monad m
+ => Lens' (Producer ByteString m r)
+ (Producer Text m (Producer ByteString m r))
+
+
+{- | @decode@ is just the ordinary @view@ or @(^.)@ of the lens libraries;
+ exported here under a name appropriate to the material. Thus
+
+> decode utf8 bytes :: Producer Text IO (Producer ByteString IO ())
+
+ All of these are thus the same:
+
+> decode utf8 bytes = view utf8 bytes = bytes ^. utf8 = decodeUtf8 bytes
+
+
+-}
+
+decode :: ((b -> Constant b b) -> (a -> Constant b a)) -> a -> b
+decode codec a = getConstant (codec Constant a)
+
+{- | @eof@ tells you explicitly when decoding stops due to bad bytes or
+ instead reaches end-of-file happily. (Without it one just makes an explicit
+ test for emptiness of the resulting bytestring production using next) Thus
+
+> decode (utf8 . eof) bytes :: Producer T.Text IO (Either (Producer B.ByteString IO ()) ())
+
+ If we hit undecodable bytes, the remaining bytestring producer will be
+ returned as a Left value; in the happy case, a Right value is returned
+ with the anticipated return value for the original bytestring producer.
+
+ Again, all of these are the same
+
+> decode (utf8 . eof) bytes = view (utf8 . eof) p = p^.utf8.eof
+
+-}
+
+eof :: (Monad m, Monad (t m), MonadTrans t) => Lens' (t m (Producer ByteString m r))
+ (t m (Either (Producer ByteString m r) r))
+eof k p0 = fmap fromEither (k (toEither p0)) where
+
+ fromEither = liftM (either id return)
+
+ toEither pp = do p <- pp
+ check p
+
+ check p = do e <- lift (next p)
+ case e of
+ Left r -> return (Right r)
+ Right (bs,pb) -> if B.null bs
+ then check pb
+ else return (Left (do yield bs
+ pb))
+