1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE ViewPatterns #-}
10{-# LANGUAGE RankNTypes #-}
11{-# LANGUAGE UndecidableInstances #-} -- XXX
14-- Module : Streamly.Streams.StreamKType
15-- Copyright : (c) 2017 Harendra Kumar
18-- Maintainer : harendra.kumar@gmail.com
19-- Stability : experimental
23-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
24-- denotes a function as well as a Kontinuation.
26module Streamly.Streams.StreamKType
28 -- * A class for streams
50 , Streaming -- deprecated
54import Control.Monad (void)
55import Control.Monad.IO.Class (MonadIO(liftIO))
56import Control.Monad.Trans.Class (MonadTrans(lift))
57import Data.Semigroup (Semigroup(..))
58import Prelude hiding (map)
62------------------------------------------------------------------------------
63-- Types that can behave as a Stream
64------------------------------------------------------------------------------
69-- XXX Use a different SVar based on the stream type. But we need to make sure
70-- that we do not lose performance due to polymorphism.
72-- | Class of types that can represent a stream of elements of some type 'a' in
77 toStream :: t m a -> Stream m a
78 fromStream :: Stream m a -> t m a
79 -- | Constructs a stream by adding a monadic action at the head of an
80 -- existing stream. For example:
83 -- > toList $ getLine \`consM` getLine \`consM` nil
89 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
92 consM :: MonadAsync m => m a -> t m a -> t m a
93 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
94 -- to remember that @|@ comes before ':'.
97 -- > toList $ getLine |: getLine |: nil
104 -- let delay = threadDelay 1000000 >> print 1
105 -- runStream $ serially $ delay |: delay |: delay |: nil
106 -- runStream $ parallely $ delay |: delay |: delay |: nil
109 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
112 (|:) :: MonadAsync m => m a -> t m a -> t m a
113 -- We can define (|:) just as 'consM' but it is defined explicitly for each
114 -- type because we want to use SPECIALIZE pragma on the definition.
116-- | Same as 'IsStream'.
119{-# DEPRECATED Streaming "Please use IsStream instead." #-}
120type Streaming = IsStream
122-------------------------------------------------------------------------------
123-- Type adapting combinators
124-------------------------------------------------------------------------------
126-- XXX Move/reset the State here by reconstructing the stream with cleared
127-- state. Can we make sure we do not do that when t1 = t2? If we do this then
128-- we do not need to do that explicitly using svarStyle. It would act as
129-- unShare when the stream type is the same.
131-- | Adapt any specific stream type to any other specific stream type.
134adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
135adapt = fromStream . toStream
137------------------------------------------------------------------------------
139------------------------------------------------------------------------------
141-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
142-- constructed using actions in monad 'm'. It uses stop, singleton and yield
143-- continuations equivalent to the following direct style type:
146-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
149-- To facilitate parallel composition we maintain a local state in an 'SVar'
150-- that is shared across and is used for synchronization of the streams being
153-- The singleton case can be expressed in terms of stop and yield but we have
154-- it as a separate case to optimize composition operations for streams with
155-- single element. We build singleton streams in the implementation of 'pure'
156-- for Applicative and Monad, and in 'lift' for MonadTrans.
158-- XXX remove the Stream type parameter from State as it is always constant.
159-- We can remove it from SVar as well
163 State Stream m a -- state
165 -> (a -> m r) -- singleton
166 -> (a -> Stream m a -> m r) -- yield
170------------------------------------------------------------------------------
172------------------------------------------------------------------------------
174-- XXX The State is always parameterized by "Stream" which means State is not
175-- different for different stream types. So we have to manually make sure that
176-- when converting from one stream to another we migrate the state correctly.
177-- This can be fixed if we use a different SVar type for different streams.
178-- Currently we always use "SVar Stream" and therefore a different State type
179-- parameterized by that stream.
181-- XXX change the order of arguments to match the standard fold function
182-- convention i.e. st yield single stop.
184-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
185-- continuation and a yield continuation.
187 => (forall r. State Stream m a
190 -> (a -> t m a -> m r)
193mkStream k = fromStream $ MkStream $ \st stp sng yld ->
194 let yieldk a r = yld a (toStream r)
195 in k st stp sng yieldk
197------------------------------------------------------------------------------
199------------------------------------------------------------------------------
201-- | Fold a stream by providing an SVar, a stop continuation, a singleton
202-- continuation and a yield continuation. The stream would share the current
203-- SVar passed via the State.
204{-# INLINE foldStreamShared #-}
210 -> (a -> t m a -> m r)
213foldStreamShared st stp sng yld m =
214 let yieldk a x = yld a (fromStream x)
215 MkStream k = toStream m
216 in k st stp sng yieldk
218-- | Fold a stream by providing a State, stop continuation, a singleton
219-- continuation and a yield continuation. The stream will not use the SVar
221{-# INLINE foldStream #-}
227 -> (a -> t m a -> m r)
230foldStream st stp sng yld m =
231 let yieldk a x = yld a (fromStream x)
232 MkStream k = toStream m
233 in k (adaptState st) stp sng yieldk
235-- Run the stream using a run function associated with the SVar that runs the
236-- streams with a captured snapshot of the monadic state.
237{-# INLINE foldStreamSVar #-}
239 :: (IsStream t, MonadIO m)
241 -> State Stream m a -- state
243 -> (a -> m r) -- singleton
244 -> (a -> t m a -> m r) -- yield
247foldStreamSVar sv st stp sng yld m =
248 let mrun = runInIO $ svarMrun sv
249 in void $ liftIO $ mrun $ foldStreamShared st stp sng yld m
251-------------------------------------------------------------------------------
253-------------------------------------------------------------------------------
255{-# INLINE consMSerial #-}
256consMSerial :: (IsStream t, Monad m) => m a -> t m a -> t m a
257consMSerial m r = mkStream $ \_ _ _ yld -> m >>= \a -> yld a r
259-------------------------------------------------------------------------------
261-------------------------------------------------------------------------------
263instance IsStream Stream where
268 {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
269 consM :: Monad m => m a -> Stream m a -> Stream m a
273 {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
274 (|:) :: Monad m => m a -> Stream m a -> Stream m a
277------------------------------------------------------------------------------
279------------------------------------------------------------------------------
281-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
282-- Appends two streams sequentially, yielding all elements from the first
283-- stream, and then all elements from the second stream.
287serial :: IsStream t => t m a -> t m a -> t m a
290 go m = mkStream $ \st stp sng yld ->
291 let stop = foldStream st stp sng yld m2
293 yieldk a r = yld a (go r)
294 in foldStream st stop single yieldk m
296instance Semigroup (Stream m a) where
299------------------------------------------------------------------------------
301------------------------------------------------------------------------------
311nil :: IsStream t => t m a
312nil = mkStream $ \_ stp _ _ -> stp
314instance Monoid (Stream m a) where
318-------------------------------------------------------------------------------
320-------------------------------------------------------------------------------
324map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
325map f m = mkStream $ \st stp sng yld ->
327 yieldk a r = yld (f a) (map f r)
328 in foldStream (adaptState st) stp single yieldk m
330instance Monad m => Functor (Stream m) where
333-------------------------------------------------------------------------------
335-------------------------------------------------------------------------------
338yieldM :: (Monad m, IsStream t) => m a -> t m a
339yieldM m = fromStream $ mkStream $ \_ _ single _ -> m >>= single
341instance MonadTrans Stream where
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list