module Tubes.Util
( cat
, Tubes.Util.map
, Tubes.Util.drop
, Tubes.Util.take
, Tubes.Util.takeWhile
, Tubes.Util.filter
, Tubes.Util.reduce
, Tubes.Util.every
, Tubes.Util.prompt
, Tubes.Util.display
, Tubes.Util.unyield
) where
import Prelude hiding (map)
import Control.Monad (forever, unless, replicateM_, when)
import Control.Monad.Trans
import Control.Monad.Trans.Free
import Data.Foldable
import Data.Monoid (Monoid, mappend, mempty)
import System.IO
import Tubes.Core
fix :: (a -> a) -> a
fix f = let x = f x in x
diverge :: a
diverge = fix id
cat :: Monad m => Tube a a m r
cat = forever $ do
x <- await
yield x
map :: (Monad m) => (a -> b) -> Tube a b m r
map f = for cat $ \x -> yield (f x)
drop :: Monad m => Int -> Tube a a m r
drop n = do
replicateM_ n await
cat
filter :: Monad m => (a -> Bool) -> Tube a a m r
filter pred = for cat $ \x -> when (pred x) (yield x)
takeWhile :: Monad m => (a -> Bool) -> Tube a a m ()
takeWhile pred = go
where
go = do
a <- await
if (pred a)
then do
yield a
go
else return ()
take :: Monad m => Int -> Tube a a m ()
take n = do
replicateM_ n $ do
x <- await
yield x
unyield :: Monad m => FreeT (TubeF x b) m () -> m (Maybe (b, FreeT (TubeF x b) m ()))
unyield tsk = do
tsk' <- runFreeT tsk
case tsk' of
Pure _ -> return Nothing
Free tsk'' -> do
let res = runT tsk'' diverge (\(v, k) -> Just (v, k))
return res
reduce :: Monad m
=> (x -> a -> x)
-> x
-> (x -> b)
-> Source a m ()
-> m b
reduce step begin done p0 = runFreeT p0 >>= \p' -> loop p' begin where
loop (Pure _) x = return (done x)
loop (Free p) x = runT p diverge (\(v, k) ->
runFreeT k >>= \k' -> loop k' $! step x v)
every :: (Foldable t, Monad m) => t b -> Tube a (Maybe b) m ()
every xs = (each xs >< map Just) >> yield Nothing
prompt :: Source String IO ()
prompt = do
lift . putStr $ "> "
eof <- lift isEOF
unless eof $ do
str <- lift getLine
yield str
prompt
display :: Sink String IO ()
display = forever $ do
it <- await
lift . putStrLn $ it