on b604937 help sign in
126 lines 8.0 kB history raw
1------------------------------------------------------------------------------
2-- CPP macros for common instances
3------------------------------------------------------------------------------
5-- XXX use template haskell instead and include Monoid and IsStream instances
6-- as well.
8#define MONADPARALLEL , MonadAsync m
10#define MONAD_APPLICATIVE_INSTANCE(STREAM,CONSTRAINT) \
11instance (Monad m CONSTRAINT) => Applicative (STREAM m) where { \
12 {-# INLINE pure #-}; \
13 pure = STREAM . K.yield; \
14 {-# INLINE (<*>) #-}; \
15 (<*>) = ap }
17#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
18instance Monad m => Functor (STREAM m) where { \
19 fmap = map }; \
20 \
21instance (MonadBase b m, Monad m CONSTRAINT) => MonadBase b (STREAM m) where {\
22 liftBase = liftBaseDefault }; \
23 \
24instance (MonadIO m CONSTRAINT) => MonadIO (STREAM m) where { \
25 liftIO = lift . liftIO }; \
26 \
27instance (MonadThrow m CONSTRAINT) => MonadThrow (STREAM m) where { \
28 throwM = lift . throwM }; \
29 \
30{- \
31instance (MonadError e m CONSTRAINT) => MonadError e (STREAM m) where { \
32 throwError = lift . throwError; \
33 catchError m h = \
34 fromStream $ withCatchError (toStream m) (\e -> toStream $ h e) }; \
35-} \
36 \
37instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
38 ask = lift ask; \
39 local f m = fromStream $ K.withLocal f (toStream m) }; \
40 \
41instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
42 get = lift get; \
43 put x = lift (put x); \
44 state k = lift (state k) }
46------------------------------------------------------------------------------
47-- Lists
48------------------------------------------------------------------------------
50-- Serial streams can act like regular lists using the Identity monad
52-- XXX Show instance is 10x slower compared to read, we can do much better.
53-- The list show instance itself is really slow.
55-- XXX The default definitions of "<" in the Ord instance etc. do not perform
56-- well, because they do not get inlined. Need to add INLINE in Ord class in
57-- base?
59#define LIST_INSTANCES(STREAM) \
60instance IsList (STREAM Identity a) where { \
61 type (Item (STREAM Identity a)) = a; \
62 {-# INLINE fromList #-}; \
63 fromList = P.fromList; \
64 {-# INLINE toList #-}; \
65 toList = runIdentity . P.toList }; \
66 \
67instance Eq a => Eq (STREAM Identity a) where { \
68 {-# INLINE (==) #-}; \
69 (==) xs ys = runIdentity $ P.eqBy (==) xs ys }; \
70 \
71instance Ord a => Ord (STREAM Identity a) where { \
72 {-# INLINE compare #-}; \
73 compare xs ys = runIdentity $ P.cmpBy compare xs ys; \
74 {-# INLINE (<) #-}; \
75 x < y = case compare x y of { LT -> True; _ -> False }; \
76 {-# INLINE (<=) #-}; \
77 x <= y = case compare x y of { GT -> False; _ -> True }; \
78 {-# INLINE (>) #-}; \
79 x > y = case compare x y of { GT -> True; _ -> False }; \
80 {-# INLINE (>=) #-}; \
81 x >= y = case compare x y of { LT -> False; _ -> True }; \
82 {-# INLINE max #-}; \
83 max x y = if x <= y then y else x; \
84 {-# INLINE min #-}; \
85 min x y = if x <= y then x else y; }; \
86 \
87instance Show a => Show (STREAM Identity a) where { \
88 showsPrec p dl = showParen (p > 10) $ \
89 showString "fromList " . shows (toList dl) }; \
90 \
91instance Read a => Read (STREAM Identity a) where { \
92 readPrec = parens $ prec 10 $ do { \
93 Ident "fromList" <- lexP; \
94 fromList <$> readPrec }; \
95 readListPrec = readListPrecDefault }; \
96 \
97instance (a ~ Char) => IsString (STREAM Identity a) where { \
98 {-# INLINE fromString #-}; \
99 fromString = P.fromList }; \
100 \
101instance NFData a => NFData (STREAM Identity a) where { rnf = rnf1 }; \
102instance NFData1 (STREAM Identity) where { \
103 {-# INLINE liftRnf #-}; \
104 liftRnf r = runIdentity . P.foldl' (\_ x -> r x) () }
106-------------------------------------------------------------------------------
107-- Foldable
108-------------------------------------------------------------------------------
110-- XXX the foldable instance seems to be quit slow. We can try writing
111-- custom implementations of foldr and foldl'. If nothing works we can also try
112-- writing a Foldable for Identity monad rather than for "Foldable m".
113#define FOLDABLE_INSTANCE(STREAM) \
114instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
115 {-# INLINE foldMap #-}; \
116 foldMap f = fold . P.foldr mappend mempty . fmap f }
118-------------------------------------------------------------------------------
119-- Traversable
120-------------------------------------------------------------------------------
122#define TRAVERSABLE_INSTANCE(STREAM) \
123instance Traversable (STREAM Identity) where { \
124 {-# INLINE traverse #-}; \
125 traverse f s = runIdentity $ P.foldr consA (pure mempty) s \
126 where { consA x ys = liftA2 K.cons (f x) ys }}