@@ -10,7 +10,7 @@ module Data.Conduit
10 , Sink (..)
10 , Sink (..)
12 -- * Connect pieces together
12 -- * Connect pieces together
14 , connectLeft
14 , connectLeft
15 , connectRight
15 , connectRight
16 -- * Helper functions
16 -- * Helper functions
@@ -24,6 +24,7 @@ import Control.Exception.Lifted (throwIO, Exception)
24import qualified Data.IORef as I
24import qualified Data.IORef as I
25import Data.Typeable (Typeable)
25import Data.Typeable (Typeable)
26import Control.Monad (liftM)
26import Control.Monad (liftM)
27+import Control.Applicative (Applicative (..))
28data Stream a = EOF | Chunks [a]
29data Stream a = EOF | Chunks [a]
29 deriving Show
30 deriving Show
@@ -49,6 +50,63 @@ instance Monad m => Functor (Sink input m) where
49 fmap f (Sink msink) = Sink $ do
50 fmap f (Sink msink) = Sink $ do
50 sink <- msink
51 sink <- msink
51 return $ \stream -> liftM (fmap f) (sink stream)
52 return $ \stream -> liftM (fmap f) (sink stream)
53+instance MonadBaseControl IO m => Applicative (Sink input m) where
55+ Sink (return (\s -> return (SinkResult (toList s) (Just x))))
58+ toList (Chunks a) = a
59+ Sink mf <*> Sink ma = Sink $ do
60+ istate <- liftBase $ I.newIORef Nothing
63+ return $ appHelper istate f a
65+appHelper :: MonadBaseControl IO m
66+ => I.IORef (Maybe (Either (b -> c) ()))
67+ -> SinkInside a m (b -> c)
70+appHelper istate f a stream = do
71+ state <- liftBase $ I.readIORef istate
74+ go Nothing stream = do
75+ SinkResult leftover mres <- f stream
77+ Nothing -> return $ SinkResult leftover Nothing
79+ let state' = Just $ Left res
80+ liftBase $ I.writeIORef istate state'
82+ then return $ SinkResult [] Nothing
83+ else go state' $ Chunks leftover
85+instance MonadBaseControl IO m => Monad (Sink input m) where
87+ x >>= f = sinkJoin (fmap f x)
89+sinkJoin :: MonadBaseControl IO m => Sink a m (Sink a m b) -> Sink a m b
90+sinkJoin (Sink mmsink) = Sink $ do
91+ istate <- liftBase $ I.newIORef Nothing
93+ return $ go istate msink
95+ go :: MonadBaseControl IO m => I.IORef (Maybe (SinkInside a m b)) -> SinkInside a m (Sink a m b) -> SinkInside a m b
96+ go istate outer stream = do
97+ state <- liftBase $ I.readIORef istate
100+ SinkResult leftover minner <- outer stream
102+ Just (Sink minner) -> do
104+ liftBase $ I.writeIORef istate $ Just inner
106+ then return $ SinkResult [] Nothing
107+ else go istate outer $ Chunks leftover
108+ Nothing -> return $ SinkResult leftover Nothing
109+ Just inner -> inner stream
53type Conduit a m b = Stream a -> ResourceT m (ConduitResult a b)
111type Conduit a m b = Stream a -> ResourceT m (ConduitResult a b)
@@ -70,8 +128,8 @@ mkSource pull = Source $ do
70 I.atomicModifyIORef buffer (\a -> (s ++ a, ()))
128 I.atomicModifyIORef buffer (\a -> (s ++ a, ()))
73−connect :: MonadBaseControl IO m => Source m a -> Sink a m b -> ResourceT m b
131+($$) :: MonadBaseControl IO m => Source m a -> Sink a m b -> ResourceT m b
74−connect (Source msource) (Sink msink) = do
132+Source msource $$ Sink msink = do
75 sink <- msink
133 sink <- msink
76 source <- msource
134 source <- msource
77 connect' source sink
135 connect' source sink