1{-# LANGUAGE UndecidableInstances #-}
4-- Module : Streamly.Internal.Data.Stream.Cross
5-- Copyright : (c) 2017 Composewell Technologies
8-- Maintainer : streamly@composewell.com
9-- Stability : experimental
12module Streamly.Internal.Data.Stream.Cross
18import Control.Monad.Catch (MonadThrow, throwM)
19import Control.Monad.Trans.Class (MonadTrans(lift))
20import Control.Applicative (liftA2)
21import Control.Monad.IO.Class (MonadIO(..))
22import Data.Functor.Identity (Identity(..))
23import GHC.Exts (IsList(..), IsString(..))
24import Streamly.Internal.Data.Stream.Type (Stream)
26import qualified Streamly.Internal.Data.Stream.Type as Stream
27import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
30-- >>> import Streamly.Internal.Data.Stream.Cross (CrossStream(..))
31-- >>> import qualified Streamly.Data.Fold as Fold
32-- >>> import qualified Streamly.Data.Stream as Stream
34------------------------------------------------------------------------------
35-- Stream with a cross product style monad instance
36------------------------------------------------------------------------------
38-- | A newtype wrapper for the 'Stream' type with a cross product style monad
41-- Semigroup instance appends two streams.
43-- A 'Monad' bind behaves like a @for@ loop:
46-- Stream.fold Fold.toList $ unCrossStream $ do
47-- x <- CrossStream (Stream.fromList [1,2]) -- foreach x in stream
52-- Nested monad binds behave like nested @for@ loops:
55-- Stream.fold Fold.toList $ unCrossStream $ do
56-- x <- CrossStream (Stream.fromList [1,2]) -- foreach x in stream
57-- y <- CrossStream (Stream.fromList [3,4]) -- foreach y in stream
60-- [(1,3),(1,4),(2,3),(2,4)]
62newtype CrossStream m a = CrossStream {unCrossStream :: Stream m a}
63 deriving (Functor, Semigroup, Monoid, Foldable)
65-- Pure (Identity monad) stream instances
66deriving instance Traversable (CrossStream Identity)
67deriving instance IsList (CrossStream Identity a)
68deriving instance (a ~ Char) => IsString (CrossStream Identity a)
69deriving instance Eq a => Eq (CrossStream Identity a)
70deriving instance Ord a => Ord (CrossStream Identity a)
71deriving instance Show a => Show (CrossStream Identity a)
72deriving instance Read a => Read (CrossStream Identity a)
74------------------------------------------------------------------------------
76------------------------------------------------------------------------------
78-- Note: we need to define all the typeclass operations because we want to
80instance Monad m => Applicative (CrossStream m) where
82 pure x = CrossStream (Stream.fromPure x)
85 (CrossStream s1) <*> (CrossStream s2) =
86 CrossStream (Stream.crossApply s1 s2)
87 -- (<*>) = K.crossApply
90 liftA2 f x = (<*>) (fmap f x)
93 (CrossStream s1) *> (CrossStream s2) =
94 CrossStream (Stream.crossApplySnd s1 s2)
95 -- (*>) = K.crossApplySnd
98 (CrossStream s1) <* (CrossStream s2) =
99 CrossStream (Stream.crossApplyFst s1 s2)
100 -- (<*) = K.crossApplyFst
102------------------------------------------------------------------------------
104------------------------------------------------------------------------------
106instance Monad m => Monad (CrossStream m) where
109 -- Benchmarks better with StreamD bind and pure:
110 -- toList, filterAllout, *>, *<, >> (~2x)
112 -- pure = Stream . D.fromStreamD . D.fromPure
113 -- m >>= f = D.fromStreamD $ D.concatMap (D.toStreamD . f) (D.toStreamD m)
115 -- Benchmarks better with CPS bind and pure:
117 -- n binds, breakAfterSome, filterAllIn, state transformer (~2x)
120 (>>=) (CrossStream m) f =
126 (Stream.toStreamK . unCrossStream . f))
131------------------------------------------------------------------------------
133------------------------------------------------------------------------------
135instance (MonadIO m) => MonadIO (CrossStream m) where
136 liftIO x = CrossStream (Stream.fromEffect $ liftIO x)
138instance MonadTrans CrossStream where
140 lift x = CrossStream (Stream.fromEffect x)
142instance (MonadThrow m) => MonadThrow (CrossStream m) where
143 throwM = lift . throwM
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