module Control.Proxy.Core.Correct (
ProxyCorrect(..),
ProxyF(..),
runProxy,
runProxyK,
runPipe
) where
import Control.Applicative (Applicative(pure, (<*>)))
import Control.Monad.IO.Class (MonadIO(liftIO))
import Control.Monad.Morph (MFunctor(hoist))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Proxy.Class (
Proxy(request, respond, (->>), (>>~)),
ProxyInternal(return_P, (?>=), lift_P, liftIO_P, hoist_P) )
import Control.Proxy.ListT (ListT((//>), (>\\)))
data ProxyCorrect a' a b' b m r =
Proxy { unProxy :: m (ProxyF a' a b' b r (ProxyCorrect a' a b' b m r)) }
data ProxyF a' a b' b r x
= Request a' (a -> x)
| Respond b (b' -> x)
| Pure r
instance (Monad m) => Functor (ProxyCorrect a' a b' b m) where
fmap f p0 = go p0 where
go p = Proxy (do
x <- unProxy p
return (case x of
Request a' fa -> Request a' (\a -> go (fa a ))
Respond b fb' -> Respond b (\b' -> go (fb' b'))
Pure r -> Pure (f r) ) )
instance (Monad m) => Applicative (ProxyCorrect a' a b' b m) where
pure r = Proxy (return (Pure r))
pf <*> px = go pf where
go p = Proxy (do
x <- unProxy p
case x of
Request a' fa -> return (Request a' (\a -> go (fa a )))
Respond b fb' -> return (Respond b (\b' -> go (fb' b')))
Pure f -> unProxy (fmap f px) )
instance (Monad m) => Monad (ProxyCorrect a' a b' b m) where
return = \r -> Proxy (return (Pure r))
p0 >>= f = go p0 where
go p = Proxy (do
x <- unProxy p
case x of
Request a' fa -> return (Request a' (\a -> go (fa a )))
Respond b fb' -> return (Respond b (\b' -> go (fb' b')))
Pure r -> unProxy (f r) )
instance MonadTrans (ProxyCorrect a' a b' b) where
lift m = Proxy (m >>= \r -> return (Pure r))
instance MFunctor (ProxyCorrect a' a b' b) where
hoist nat p0 = go p0 where
go p = Proxy (nat (do
x <- unProxy p
return (case x of
Request a' fa -> Request a' (\a -> go (fa a ))
Respond b fb' -> Respond b (\b' -> go (fb' b'))
Pure r -> Pure r )))
instance (MonadIO m) => MonadIO (ProxyCorrect a' a b' b m) where
liftIO m = Proxy (liftIO (m >>= \r -> return (Pure r)))
instance ProxyInternal ProxyCorrect where
return_P = return
(?>=) = (>>=)
lift_P = lift
hoist_P = hoist
liftIO_P = liftIO
instance Proxy ProxyCorrect where
fb' ->> p = Proxy (do
x <- unProxy p
case x of
Request b' fb -> unProxy (fb' b' >>~ fb)
Respond c fc' -> return (Respond c (\c' -> fb' ->> fc' c'))
Pure r -> return (Pure r) )
p >>~ fb = Proxy (do
x <- unProxy p
case x of
Request a' fa -> return (Request a' (\a -> fa a >>~ fb))
Respond b fb' -> unProxy (fb' ->> fb b)
Pure r -> return (Pure r) )
request = \a' -> Proxy (return (Request a' (\a ->
Proxy (return (Pure a )))))
respond = \b -> Proxy (return (Respond b (\b' ->
Proxy (return (Pure b')))))
instance ListT ProxyCorrect where
fb' >\\ p0 = go p0 where
go p = Proxy (do
x <- unProxy p
case x of
Request b' fb -> unProxy (fb' b' >>= \b -> go (fb b))
Respond x fx' -> return (Respond x (\x' -> go (fx' x')))
Pure a -> return (Pure a) )
p0 //> fb = go p0 where
go p = Proxy (do
x <- unProxy p
case x of
Request x' fx -> return (Request x' (\x -> go (fx x)))
Respond b fb' -> unProxy (fb b >>= \b' -> go (fb' b'))
Pure a -> return (Pure a) )
runProxy :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> m r
runProxy k = go (k ()) where
go p = do
x <- unProxy p
case x of
Request _ fa -> go (fa ())
Respond _ fb' -> go (fb' ())
Pure r -> return r
runProxyK :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> (() -> m r)
runProxyK p = \() -> runProxy p
runPipe :: (Monad m) => ProxyCorrect a' () () b m r -> m r
runPipe p = runProxy (\_ -> p)