> {-# LANGUAGE RankNTypes, TupleSections #-}
> module Control.Quiver (
>   Q,
>   consume, produce, enclose, deliver,
>   decouple, evacuate,
>   fetch, fetch',
>   emit, emit', emit_,
>   liftQ,
>   (>>->), (>->>),
> ) where
> import Control.Quiver.Internal
> infixl 0 >>->, >->>
> fetch :: a' -> Q a' a b' b f (Maybe a)
> fetch x = Consume x (Deliver . Just) (Deliver Nothing)
> fetch' :: a' -> (forall x' x . Q x' x b' b f a) -> Q a' a b' b f a
> fetch' x r = Consume x Deliver r
> emit :: b -> Q a' a b' b f (Maybe b')
> emit y = Produce y (Deliver . Just) (Deliver Nothing)
> emit' :: b -> (forall x' x . Q a' a x' x f b') -> Q a' a b' b f b'
> emit' y r = Produce y Deliver r
> emit_ :: b -> Q a' a b' b f ()
> emit_ y = Produce y (Deliver . const ()) (Deliver ())
> liftQ :: Functor f => f c -> Q a' a b' b f c
> liftQ = Enclose . fmap Deliver
> (>>->) :: Functor f => Q a' a t' t f c1 -> Q t' t b' b f c2 -> Q a' a b' b f (c1, c2)
> (Consume x1 k1 r1) >>-> q2 = Consume x1 ((>>-> q2) . k1) (r1 >>-> q2)
> (Produce y1 k1 r1) >>-> q2 = loop q2
>  where
>   loop  (Consume x2 k2  _) = k1 x2 >>-> k2 y1
>   loop  (Produce y2 k2 r2) = Produce y2 (loop . k2) (loop' r2)
>   loop  (Enclose f2)       = Enclose (fmap loop f2)
>   loop  (Deliver z2)       = fmap (, z2) r1
>   loop' (Consume x2 k2  _) = k1 x2 >>-> k2 y1
>   loop' (Produce  _  _ r2) = loop' r2
>   loop' (Enclose f2)       = Enclose (fmap loop' f2)
>   loop' (Deliver z2)       = fmap (, z2) r1
> (Enclose f1) >>-> q2 = Enclose (fmap (>>-> q2) f1)
> (Deliver z1) >>-> q2 = fmap (z1 ,) (decouple q2)
> (>->>) :: Functor f => Q a' a t' t f c1 -> Q t' t b' b f c2 -> Q a' a b' b f (c1, c2)
> q1 >->> (Consume x2 k2 r2) = loop q1
>  where
>   loop  (Consume x1 k1 r1) = Consume x1 (loop . k1) (loop' r1)
>   loop  (Produce y1 k1  _) = k1 x2 >->> k2 y1
>   loop  (Enclose f1)       = Enclose (fmap loop f1)
>   loop  (Deliver z1)       = fmap (z1 ,) r2
>   loop' (Consume  _  _ t1) = loop' t1
>   loop' (Produce y1 k1  _) = k1 x2 >->> k2 y1
>   loop' (Enclose f1)       = Enclose (fmap loop' f1)
>   loop' (Deliver z1)       = fmap (z1 ,) r2
> q1 >->> (Produce y2 k2 r2) = Produce y2 ((q1 >->>) . k2) (q1 >->> r2)
> q1 >->> (Enclose f2)       = Enclose (fmap (q1 >->>) f2)
> q1 >->> (Deliver z2)       = fmap (, z2) (evacuate q1)