{-| An interpreter that fails randomly -} {-# LANGUAGE TypeFamilies #-} module Network.HTTP.Client.Free.ArbitraryClient where import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Trans (MonadTrans, lift) import Control.Monad.Trans.Free.Church (FT, iterT, iterTM, liftF) import Control.Applicative ((<$>)) import Network.HTTP.Client.Free.Types (HttpF(HttpF), ResponseType) import Test.QuickCheck (Arbitrary, arbitrary, sample') ------------------------------------------------------------------------------- -- | Peel a layer of the 'HttpF' functor and generate a random Response. iterTHttp :: ( r ~ ResponseType client , Arbitrary r , Monad m , MonadIO m ) => HttpF client (m a) -> m a iterTHttp (HttpF _ _ next) = head <$> liftIO (sample' arbitrary) >>= next ------------------------------------------------------------------------------- -- | Peel a layer of the 'HttpF' functor and generate a random Response. This -- time the base monad is 't m'. iterTMHttp :: ( r ~ ResponseType client , Arbitrary r , Monad m , MonadIO m , MonadTrans t , Monad (t m) ) => HttpF client (t m a) -> t m a iterTMHttp (HttpF _ _ next) = head <$> (lift . liftIO) (sample' arbitrary) >>= next ------------------------------------------------------------------------------- -- | The main http-client interpreter. The client is free to specify the base -- effect monad so long as there is an instance of 'MonadIO' for it in scope. runHttp :: ( r ~ ResponseType client , Arbitrary r , Monad m , MonadIO m ) => ignore -- ^ a paramter that will be ignored. It is included so client's can -- hot-swap interpreters. -> FT (HttpF client) m a -> m a runHttp = const (iterT iterTHttp) ------------------------------------------------------------------------------- -- | The main http-client interpreter. The client is free to specify the base -- effect monad ('m'), and in thise case this the result can be lifted into a -- higher monad transformer stack ('t') runTHttp :: ( r ~ ResponseType client , Arbitrary r , Monad m , MonadIO m , MonadTrans t , Monad (t m) ) => ignore -- ^ a paramter that will be ignored. It is included so client's can -- hot-swap interpreters. -> FT (HttpF client) m a -> t m a runTHttp = const (iterTM iterTMHttp)