Copyright | (c) Ivan Perez and Manuel Baerenz 2016 |
---|---|
License | BSD3 |
Maintainer | ivan.perez@keera.co.uk |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Monadic Stream Functions are synchronized stream functions with side effects.
MSF
s are defined by a function
unMSF :: MSF m a b -> a -> m (b, MSF m a b)
that executes one step of a simulation, and produces an output in a monadic
context, and a continuation to be used for future steps.
MSF
s are a generalisation of the implementation mechanism used by Yampa,
Wormholes and other FRP and reactive implementations.
When combined with different monads, they produce interesting effects. For
example, when combined with the Maybe
monad, they become transformations
that may stop producing outputs (and continuations). The Either
monad
gives rise to MSF
s that end with a result (akin to Tasks in Yampa, and
Monadic FRP).
Flattening, that is, going from some structure MSF (t m) a b
to MSF m a b
for a specific transformer t
often gives rise to known FRP constructs.
For instance, flattening with EitherT
gives rise to switching, and
flattening with ListT
gives rise to parallelism with broadcasting.
MSF
s can be used to implement many FRP variants, including Arrowized FRP,
Classic FRP, and plain reactive programming. Arrowized and applicative
syntax are both supported.
For a very detailed introduction to MSF
s, see:
http://dl.acm.org/citation.cfm?id=2976010
(mirror: http://www.cs.nott.ac.uk/~psxip1/#FRPRefactored).
Synopsis
- data MSF m a b
- constM :: Monad m => m b -> MSF m a b
- arrM :: Monad m => (a -> m b) -> MSF m a b
- liftBaseM :: (Monad m2, MonadBase m1 m2) => (a -> m1 b) -> MSF m2 a b
- liftBaseS :: (Monad m2, MonadBase m1 m2) => MSF m1 a b -> MSF m2 a b
- (^>>>) :: MonadBase m1 m2 => MSF m1 a b -> MSF m2 b c -> MSF m2 a c
- (>>>^) :: MonadBase m1 m2 => MSF m2 a b -> MSF m1 b c -> MSF m2 a c
- liftTransS :: (MonadTrans t, Monad m, Monad (t m)) => MSF m a b -> MSF (t m) a b
- morphS :: (Monad m2, Monad m1) => (forall c. m1 c -> m2 c) -> MSF m1 a b -> MSF m2 a b
- morphGS :: Monad m2 => (forall c. (a1 -> m1 (b1, c)) -> a2 -> m2 (b2, c)) -> MSF m1 a1 b1 -> MSF m2 a2 b2
- feedback :: Monad m => c -> MSF m (a, c) (b, c) -> MSF m a b
- reactimate :: Monad m => MSF m () () -> m ()
- embed :: Monad m => MSF m a b -> [a] -> m [b]
- module Control.Arrow
Types
Stepwise, side-effectful MSF
s without implicit knowledge of time.
MSF
s should be applied to streams or executed indefinitely or until they
terminate. See reactimate
and reactimateB
for details. In general,
calling the value constructor MSF
or the function unMSF
is discouraged.
Instances
Monad m => Category (MSF m :: Type -> Type -> Type) Source # | |
Monad m => Arrow (MSF m) Source # | |
Monad m => ArrowChoice (MSF m) Source # |
|
MonadFix m => ArrowLoop (MSF m) Source # |
|
(Monad m, MonadPlus m) => ArrowPlus (MSF m) Source # | Instance of |
(Monad m, MonadPlus m) => ArrowZero (MSF m) Source # | Instance of |
(Functor m, Monad m, MonadPlus m) => Alternative (MSF m a) Source # | Instance of |
(Functor m, Monad m) => Applicative (MSF m a) Source # |
|
Monad m => Functor (MSF m a) Source # | |
(Monad m, Floating b) => Floating (MSF m a b) Source # | |
Defined in Data.MonadicStreamFunction.Instances.Num exp :: MSF m a b -> MSF m a b # log :: MSF m a b -> MSF m a b # sqrt :: MSF m a b -> MSF m a b # (**) :: MSF m a b -> MSF m a b -> MSF m a b # logBase :: MSF m a b -> MSF m a b -> MSF m a b # sin :: MSF m a b -> MSF m a b # cos :: MSF m a b -> MSF m a b # tan :: MSF m a b -> MSF m a b # asin :: MSF m a b -> MSF m a b # acos :: MSF m a b -> MSF m a b # atan :: MSF m a b -> MSF m a b # sinh :: MSF m a b -> MSF m a b # cosh :: MSF m a b -> MSF m a b # tanh :: MSF m a b -> MSF m a b # asinh :: MSF m a b -> MSF m a b # acosh :: MSF m a b -> MSF m a b # atanh :: MSF m a b -> MSF m a b # log1p :: MSF m a b -> MSF m a b # expm1 :: MSF m a b -> MSF m a b # | |
(Monad m, Num b) => Num (MSF m a b) Source # | |
Defined in Data.MonadicStreamFunction.Instances.Num | |
(Monad m, Fractional b) => Fractional (MSF m a b) Source # |
|
(Monad m, Eq s, Num s, VectorSpace v s, Floating (MSF m a s)) => VectorSpace (MSF m a v) (MSF m a s) Source # | Vector-space instance for |
Defined in Data.MonadicStreamFunction.Instances.VectorSpace zeroVector :: MSF m a v # (*^) :: MSF m a s -> MSF m a v -> MSF m a v # (^/) :: MSF m a v -> MSF m a s -> MSF m a v # (^+^) :: MSF m a v -> MSF m a v -> MSF m a v # (^-^) :: MSF m a v -> MSF m a v -> MSF m a v # negateVector :: MSF m a v -> MSF m a v # dot :: MSF m a v -> MSF m a v -> MSF m a s # |
Lifting and Monadic transformations
Lifting point-wise computations
liftBaseM :: (Monad m2, MonadBase m1 m2) => (a -> m1 b) -> MSF m2 a b Source #
Monadic lifting from one monad into another
Trans-monadic MSF combinators
MonadBase
liftBaseS :: (Monad m2, MonadBase m1 m2) => MSF m1 a b -> MSF m2 a b Source #
Lift innermost monadic actions in monad stack (generalisation of
liftIO
).
(^>>>) :: MonadBase m1 m2 => MSF m1 a b -> MSF m2 b c -> MSF m2 a c Source #
Lift the first MSF
into the monad of the second.
(>>>^) :: MonadBase m1 m2 => MSF m2 a b -> MSF m1 b c -> MSF m2 a c Source #
Lift the second MSF
into the monad of the first.
MonadTrans
liftTransS :: (MonadTrans t, Monad m, Monad (t m)) => MSF m a b -> MSF (t m) a b Source #
Lift inner monadic actions in monad stacks.
Generic Monadic Transformations
morphS :: (Monad m2, Monad m1) => (forall c. m1 c -> m2 c) -> MSF m1 a b -> MSF m2 a b Source #
Apply trans-monadic actions (in an arbitrary way).
This is just a convenience function when you have a function to move across
monads, because the signature of morphGS
is a bit complex.
:: Monad m2 | |
=> (forall c. (a1 -> m1 (b1, c)) -> a2 -> m2 (b2, c)) | The natural transformation. |
-> MSF m1 a1 b1 | |
-> MSF m2 a2 b2 |
Generic lifting of a morphism to the level of MSF
s.
Natural transformation to the level of MSF
s.
Mathematical background: The type a -> m (b, c)
is a functor in c
,
and MSF m a b
is its greatest fixpoint, i.e. it is isomorphic to the type
a -> m (b, MSF m a b)
, by definition. The types m
, a
and b
are
parameters of the functor. Taking a fixpoint is functorial itself, meaning
that a morphism (a natural transformation) of two such functors gives a
morphism (an ordinary function) of their fixpoints.
This is in a sense the most general "abstract" lifting function, i.e. the
most general one that only changes input, output and side effect types, and
doesn't influence control flow. Other handling functions like exception
handling or ListT
broadcasting necessarily change control flow.
Depending on the past
feedback :: Monad m => c -> MSF m (a, c) (b, c) -> MSF m a b Source #
Well-formed looped connection of an output component as a future input.
Simulation
reactimate :: Monad m => MSF m () () -> m () Source #
Run an MSF
indefinitely passing a unit-carrying input stream.
embed :: Monad m => MSF m a b -> [a] -> m [b] Source #
Apply a monadic stream function to a list.
Because the result is in a monad, it may be necessary to traverse the whole
list to evaluate the value in the results to WHNF. For example, if the
monad is the maybe monad, this may not produce anything if the MSF
produces Nothing
at any point, so the output stream cannot consumed
progressively.
To explore the output progressively, use arrM
and (>>>)
', together with
some action that consumes/actuates on the output.
This is called runSF
in Liu, Cheng, Hudak, "Causal Commutative Arrows and
Their Optimization"
module Control.Arrow