> {-# LANGUAGE RankNTypes, TupleSections #-}
> module Control.Quiver.Internal (
>   Q (..),
>   consume, produce, enclose, deliver,
>   decouple, evacuate
> ) where
> data Q a' a b' b f c =
>     Consume a' (a  -> Q a' a b' b f c) (forall x' x . Q x' x b' b f c)
>   | Produce b  (b' -> Q a' a b' b f c) (forall x' x . Q a' a x' x f c)
>   | Enclose (f (Q a' a b' b f c))
>   | Deliver c
> consume :: a' -> (a  -> Q a' a b' b f c) -> (forall x' x . Q x' x b' b f c) -> Q a' a b' b f c
> consume = Consume
> produce :: b  -> (b' -> Q a' a b' b f c) -> (forall x' x . Q a' a x' x f c) -> Q a' a b' b f c
> produce = Produce
> enclose :: f (Q a' a b' b f c) -> Q a' a b' b f c
> enclose = Enclose
> deliver :: c -> Q a' a b' b f c
> deliver = Deliver
> instance Functor f => Functor (Q a' a b' b f) where
>   fmap ff (Consume x k r) = Consume x (fmap ff . k) (fmap ff r)
>   fmap ff (Produce y k r) = Produce y (fmap ff . k) (fmap ff r)
>   fmap ff (Enclose f)     = Enclose (fmap (fmap ff) f)
>   fmap ff (Deliver z)     = Deliver (ff z)
> instance Applicative f => Applicative (Q a' a b' b f) where
>   pure = Deliver
>   (Consume x k r) <*> q = Consume x ((<*> q) . k) (r <*> decouple q)
>   (Produce y k r) <*> q = Produce y ((<*> q) . k) (r <*> evacuate q)
>   (Enclose f)     <*> q = Enclose (fmap (<*> q) f)
>   (Deliver z)     <*> q = fmap z q
> instance Monad f => Monad (Q a' a b' b f) where
>   (Consume x k r) >>= kk = Consume x ((>>= kk) . k) (r >>= decouple . kk)
>   (Produce y k r) >>= kk = Produce y ((>>= kk) . k) (r >>= evacuate . kk)
>   (Enclose f)     >>= kk = Enclose (fmap (>>= kk) f)
>   (Deliver z)     >>= kk = kk z
> decouple :: Functor f => Q a' a b' b f c -> forall x' x . Q x' x b' b f c
> decouple (Consume _ _ r) = r
> decouple (Produce y k r) = Produce y (decouple . k) (decouple r)
> decouple (Enclose f) = Enclose (fmap decouple f)
> decouple (Deliver z) = Deliver z
> evacuate :: Functor f => Q a' a b' b f c -> forall x' x . Q a' a x' x f c
> evacuate (Consume x k r) = Consume x (evacuate . k) (evacuate r)
> evacuate (Produce _ _ r) = r
> evacuate (Enclose f) = Enclose (fmap evacuate f)
> evacuate (Deliver z) = Deliver z