@@ -17,6 +17,7 @@ import Data.Dependent.Map (DMap, DSum (..), GCompare (..), GOrdering (..))
1717import qualified Data.Dependent.Map as DMap
1818import Data.Functor.Misc
1919import Data.Semigroup
20+import Data.Traversable
2021
2122import Debug.Trace (trace)
2223
@@ -82,12 +83,27 @@ ffor = flip fmap
8283instance Reflex t => Functor (Behavior t) where
8384 fmap f = pull . liftM f . sample
8485
85−--TODO: Rewrite rules for Applicative
8686instance Reflex t => Applicative (Behavior t) where
8787 pure = constant
88− f <*> x = pull $ sample f <*> sample x
89− a *> b = b
90− a <* b = a
88+ f <*> x = pull $ sample f `ap` sample x
89+ _ *> b = b
90+ a <* _ = a
91+
92+instance Reflex t => Monad (Behavior t) where
93+ a >>= f = pull $ sample a >>= sample . f
94+ -- Note: it is tempting to write (_ >> b = b); however, this would result in (fail x >> return y) succeeding (returning y), which violates the law that (a >> b = a >>= \_ -> b), since the implementation of (>>=) above actually will fail. Since we can't examine Behaviors other than by using sample, I don't think it's possible to write (>>) to be more efficient than the (>>=) above.
95+ return = constant
96+ fail = error "Monad (Behavior t) does not support fail"
97+
98+instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
99+ a <> b = pull $ liftM2 (<>) (sample a) (sample b)
100+ sconcat = pull . liftM sconcat . mapM sample
101+ times1p n = fmap $ times1p n
102+
103+instance (Reflex t, Monoid a) => Monoid (Behavior t a) where
104+ mempty = constant mempty
105+ mappend a b = pull $ liftM2 mappend (sample a) (sample b)
106+ mconcat = pull . liftM mconcat . mapM sample
91107
92108--TODO: See if there's a better class in the standard libraries already
93109-- | A class for values that combines filtering and mapping using 'Maybe'.