pipes-2.5.0: Control/Proxy/Prelude/Kleisli.hs
-- | Utility functions for Kleisli arrows
module Control.Proxy.Prelude.Kleisli (
-- * Core utility functions
-- $utility
foreverK,
replicateK,
mapK
) where
import Control.Monad (forever, (>=>))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Proxy.Class (Interact(request, respond))
import Data.Closed (C)
{- $utility
Use 'foreverK' to abstract away the following common pattern:
> p a = do
> ...
> a' <- respond b
> p a'
Using 'foreverK', you can avoid the manual recursion:
> p = foreverK $ \a -> do
> ...
> respond b
-}
-- | Compose a \'@K@\'leisli arrow with itself forever
foreverK :: (Monad m) => (a -> m a) -> (a -> m b)
foreverK k = let r = k >=> r in r
{- foreverK uses 'let' to avoid a space leak.
See: http://hackage.haskell.org/trac/ghc/ticket/5205 -}
-- | Repeat a \'@K@\'leisli arrow multiple times
replicateK :: (Monad m) => Int -> (a -> m a) -> (a -> m a)
replicateK n0 k = go n0 where
go n
| n < 1 = return
| n == 1 = k
| otherwise = k >=> go (n - 1)
{-| Convenience function equivalent to @(lift .)@
> mapK f >=> mapK g = mapK (f >=> g)
>
> mapK return = return
-}
mapK :: (Monad m, MonadTrans t) => (a -> m b) -> (a -> t m b)
mapK = (lift .)
{-# INLINABLE mapK #-}