-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An asynchronous modal FRP language -- -- This library implements the Async Rattus programming language as an -- embedded DSL. To this end the library provides a GHC plugin that -- checks the stricter typing rules of Async Rattus. What follows is a -- brief introduction to the language and its usage. A more detailed -- introduction can be found in this paper. -- -- Async Rattus is a functional reactive programming (FRP) language that -- uses modal types to express temporal dependencies. In return the -- language will guarantee that programs are productive (in each -- computation step, the program makes progress), causal (output depends -- only on current and earlier input), and have no space leaks (programs -- do not implicitly retain memory over time). -- -- The modal type constructor O (pronounced "later") is used to -- express the passage of time at the type level. Intuitively speaking, a -- value of type O a represents a computation that will produce -- a value of type a in the next time step. Additionally, the -- language also features the Box modal type constructor. A -- value of type Box a is a time-independent computation that -- can be executed at any time to produce a value of type a. -- -- For example, the type of signals is defined as -- --
-- data Sig a = a ::: (O (Sig a)) ---- -- So the current value of the signal is available now, but its future -- state is only available in the next time step. Writing a map -- function for this type of streams, requires us to use the Box -- modality: -- --
-- map :: Box (a -> b) -> Sig a -> Sig b -- map f (x ::: xs) = unbox f x ::: delay (map f (adv xs)) ---- -- This makes sure that the function f that we give to -- map is available at any time in the future. -- -- The core of the language is defined in the module -- AsyncRattus.Primitives. Note that the operations on O -- and Box have non-standard typing rules. Therefore, this -- library provides a compiler plugin that checks these non-standard -- typing rules. To write Async Rattus programs, you must enable this -- plugin via the GHC option -fplugin=AsyncRattus.Plugin, e.g. -- by including the following line in the source file: -- --
-- {-# OPTIONS -fplugin=AsyncRattus.Plugin #-}
--
--
-- Below is a minimal Async Rattus program using the
-- AsyncRattus.Signal module for programming with signals:
--
--
-- {-# OPTIONS -fplugin=AsyncRattus.Plugin #-}
--
-- import AsyncRattus
-- import AsyncRattus.Signal
--
-- sums :: Sig Int -> Sig Int
-- sums = scan (box (+)) 0
--
--
-- The source code of the AsyncRattus.Signal module provides more
-- examples on how to program in Async Rattus. An example project using
-- Async Rattus can be found here.
@package AsyncRattus
@version 0.2.1
module AsyncRattus.InternalPrimitives
type InputChannelIdentifier = Int
type Clock = IntSet
singletonClock :: InputChannelIdentifier -> Clock
clockUnion :: Clock -> Clock -> Clock
channelMember :: InputChannelIdentifier -> Clock -> Bool
data InputValue
[InputValue] :: !InputChannelIdentifier -> !a -> InputValue
-- | The "later" type modality. A value v of type O 𝜏
-- consists of two components: Its clock, denoted cl(v), and a
-- delayed computation that will produce a value of type 𝜏 as
-- soon as the clock cl(v) ticks. The clock cl(v) is
-- only used for type checking and is not directly accessible, whereas
-- the delayed computation is accessible via adv and
-- select.
data O a
Delay :: !Clock -> (InputValue -> a) -> O a
-- | The return type of the select primitive.
data Select a b
Fst :: !a -> !O b -> Select a b
Snd :: !O a -> !b -> Select a b
Both :: !a -> !b -> Select a b
asyncRattusError :: [Char] -> a
-- | This is the constructor for the "later" modality O:
--
-- -- Γ ✓θ ⊢ t :: 𝜏 -- -------------------- -- Γ ⊢ delay t :: O 𝜏 ---- -- The typing rule requires that its argument t typecheck with -- an additional tick ✓θ of some clock θ. delay :: a -> O a extractClock :: O a -> Clock adv' :: O a -> InputValue -> a -- | This is the eliminator for the "later" modality O: -- --
-- Γ ⊢ t :: O 𝜏 Γ' tick-free -- --------------------------------- -- Γ ✓cl(t) Γ' ⊢ adv t :: 𝜏 ---- -- It requires that a tick ✓θ is in the context whose clock -- matches exactly the clock of t, i.e. θ = cl(t). adv :: O a -> a -- | If we want to eliminate more than one delayed computation, i.e. two -- s :: O σ and t :: O 𝜏, we need to use select -- instead of just adv. -- --
-- Γ ⊢ s :: O σ Γ ⊢ t :: O 𝜏 Γ' tick-free -- -------------------------------------------------- -- Γ ✓cl(s)⊔cl(t) Γ' ⊢ select s t :: Select σ 𝜏 ---- -- It requires that we have a tick ✓θ in the context whose clock -- matches the union of the clocks of s and t, i.e. -- θ = cl(s)⊔cl(t). The union of two clocks ticks whenever -- either of the two clocks ticks, i.e. cl(s)⊔cl(t), whenever -- cl(s) or cl(t) ticks. -- -- That means there are three possible outcomes, which are reflected in -- the result type of select s t. A value of Select σ 𝜏 -- is either -- --
-- Γ☐ ⊢ t :: 𝜏 -- -------------------- -- Γ ⊢ box t :: Box 𝜏 ---- -- where Γ☐ is obtained from Γ by removing all ticks and all variables -- x :: 𝜏, where 𝜏 is not a stable type. box :: a -> Box a -- | This is the eliminator for the "stable" modality Box: -- --
-- Γ ⊢ t :: Box 𝜏 -- ------------------ -- Γ ⊢ unbox t :: 𝜏 --unbox :: Box a -> a module AsyncRattus.Plugin.Annotation -- | By default all Async Rattus functions are checked for use of lazy data -- types, since these may cause memory leaks. If any lazy data types are -- used, a warning is issued. These warnings can be disabled by -- annotating the module or the function with AllowLazyData -- --
-- {-# ANN myFunction AllowLazyData #-}
--
-- {-# ANN module AllowLazyData #-}
--
--
-- Async Rattus only allows guarded recursion, i.e. recursive calls must
-- occur in the scope of a tick. Structural recursion over strict data
-- types is safe as well, but is currently not checked. To disable the
-- guarded recursion check, annotate the module or function with
-- AllowRecursion.
--
--
-- {-# ANN myFunction AllowRecursion #-}
--
-- {-# ANN module AllowRecursion #-}
--
data AsyncRattus
AllowLazyData :: AsyncRattus
AllowRecursion :: AsyncRattus
-- | This annotation type is for internal use only.
data InternalAnn
ExpectError :: InternalAnn
ExpectWarning :: InternalAnn
instance GHC.Classes.Eq AsyncRattus.Plugin.Annotation.AsyncRattus
instance GHC.Classes.Ord AsyncRattus.Plugin.Annotation.AsyncRattus
instance GHC.Show.Show AsyncRattus.Plugin.Annotation.AsyncRattus
instance Data.Data.Data AsyncRattus.Plugin.Annotation.AsyncRattus
instance GHC.Classes.Ord AsyncRattus.Plugin.Annotation.InternalAnn
instance GHC.Classes.Eq AsyncRattus.Plugin.Annotation.InternalAnn
instance GHC.Show.Show AsyncRattus.Plugin.Annotation.InternalAnn
instance Data.Data.Data AsyncRattus.Plugin.Annotation.InternalAnn
-- | The plugin to make it all work.
module AsyncRattus.Plugin
-- | Use this to enable Asynchronous Rattus' plugin, either by supplying
-- the option -fplugin=AsyncRattus.Plugin directly to GHC, or by
-- including the following pragma in each source file:
--
--
-- {-# OPTIONS -fplugin=AsyncRattus.Plugin #-}
--
plugin :: Plugin
-- | By default all Async Rattus functions are checked for use of lazy data
-- types, since these may cause memory leaks. If any lazy data types are
-- used, a warning is issued. These warnings can be disabled by
-- annotating the module or the function with AllowLazyData
--
--
-- {-# ANN myFunction AllowLazyData #-}
--
-- {-# ANN module AllowLazyData #-}
--
--
-- Async Rattus only allows guarded recursion, i.e. recursive calls must
-- occur in the scope of a tick. Structural recursion over strict data
-- types is safe as well, but is currently not checked. To disable the
-- guarded recursion check, annotate the module or function with
-- AllowRecursion.
--
--
-- {-# ANN myFunction AllowRecursion #-}
--
-- {-# ANN module AllowRecursion #-}
--
data AsyncRattus
AllowLazyData :: AsyncRattus
AllowRecursion :: AsyncRattus
-- | The language primitives of Async Rattus. Note that the typing rules
-- for delay, adv,select and box are more
-- restrictive than the Haskell types that are indicated. The stricter
-- Async Rattus typing rules for these primitives are given below.
module AsyncRattus.Primitives
-- | The "later" type modality. A value v of type O 𝜏
-- consists of two components: Its clock, denoted cl(v), and a
-- delayed computation that will produce a value of type 𝜏 as
-- soon as the clock cl(v) ticks. The clock cl(v) is
-- only used for type checking and is not directly accessible, whereas
-- the delayed computation is accessible via adv and
-- select.
data O a
-- | The "stable" type modality. A value of type Box a is a
-- time-independent computation that produces a value of type a.
-- Use box and unbox to construct and consume
-- Box-types.
data Box a
-- | The return type of the select primitive.
data Select a b
Fst :: !a -> !O b -> Select a b
Snd :: !O a -> !b -> Select a b
Both :: !a -> !b -> Select a b
-- | This is the constructor for the "later" modality O:
--
-- -- Γ ✓θ ⊢ t :: 𝜏 -- -------------------- -- Γ ⊢ delay t :: O 𝜏 ---- -- The typing rule requires that its argument t typecheck with -- an additional tick ✓θ of some clock θ. delay :: a -> O a -- | This is the eliminator for the "later" modality O: -- --
-- Γ ⊢ t :: O 𝜏 Γ' tick-free -- --------------------------------- -- Γ ✓cl(t) Γ' ⊢ adv t :: 𝜏 ---- -- It requires that a tick ✓θ is in the context whose clock -- matches exactly the clock of t, i.e. θ = cl(t). adv :: O a -> a -- | This is the constructor for the "stable" modality Box: -- --
-- Γ☐ ⊢ t :: 𝜏 -- -------------------- -- Γ ⊢ box t :: Box 𝜏 ---- -- where Γ☐ is obtained from Γ by removing all ticks and all variables -- x :: 𝜏, where 𝜏 is not a stable type. box :: a -> Box a -- | This is the eliminator for the "stable" modality Box: -- --
-- Γ ⊢ t :: Box 𝜏 -- ------------------ -- Γ ⊢ unbox t :: 𝜏 --unbox :: Box a -> a -- | If we want to eliminate more than one delayed computation, i.e. two -- s :: O σ and t :: O 𝜏, we need to use select -- instead of just adv. -- --
-- Γ ⊢ s :: O σ Γ ⊢ t :: O 𝜏 Γ' tick-free -- -------------------------------------------------- -- Γ ✓cl(s)⊔cl(t) Γ' ⊢ select s t :: Select σ 𝜏 ---- -- It requires that we have a tick ✓θ in the context whose clock -- matches the union of the clocks of s and t, i.e. -- θ = cl(s)⊔cl(t). The union of two clocks ticks whenever -- either of the two clocks ticks, i.e. cl(s)⊔cl(t), whenever -- cl(s) or cl(t) ticks. -- -- That means there are three possible outcomes, which are reflected in -- the result type of select s t. A value of Select σ 𝜏 -- is either -- --
-- fromListN (length xs) xs == fromList xs --fromListN :: IsList l => Int -> [Item l] -> l -- | The toList function extracts a list of Item l from the -- structure l. It should satisfy fromList . toList = id. toList :: IsList l => l -> [Item l] -- | Remove the last element from a list if there is one, otherwise return -- Nil. init' :: List a -> List a -- | Reverse a list. reverse' :: List a -> List a union' :: Eq a => List a -> List a -> List a unionBy' :: (a -> a -> Bool) -> List a -> List a -> List a nub' :: Eq a => List a -> List a nubBy' :: (a -> a -> Bool) -> List a -> List a filter' :: (a -> Bool) -> List a -> List a delete' :: Eq a => a -> List a -> List a deleteBy' :: (a -> a -> Bool) -> a -> List a -> List a -- | Append two lists. (+++) :: List a -> List a -> List a -- | Returns Nothing' on an empty list or Just' -- a where a is the first element of the list. listToMaybe' :: List a -> Maybe' a map' :: (a -> b) -> List a -> List b zip' :: List a -> List b -> List (a :* b) zipWith' :: (a -> b -> c) -> List a -> List b -> List c -- | A version of map which can throw out elements. In particular, -- the function argument returns something of type Maybe' -- b. If this is Nothing', no element is added on to the -- result list. If it is Just' b, then b is -- included in the result list. mapMaybe' :: (a -> Maybe' b) -> List a -> List b concatMap' :: (a -> List b) -> List a -> List b -- | Strict pair type. data a :* b (:*) :: !a -> !b -> (:*) a b infixr 2 :* infixr 2 :* -- | Strict variant of Maybe. data Maybe' a Just' :: !a -> Maybe' a Nothing' :: Maybe' a -- | takes a default value, a function, and a Maybe' value. If the -- Maybe' value is Nothing', the function returns the -- default value. Otherwise, it applies the function to the value inside -- the Just' and returns the result. maybe' :: b -> (a -> b) -> Maybe' a -> b fromMaybe' :: a -> Maybe' a -> a isJust' :: Maybe' a -> Bool -- | First projection function. fst' :: (a :* b) -> a -- | Second projection function. snd' :: (a :* b) -> b curry' :: ((a :* b) -> c) -> a -> b -> c uncurry' :: (a -> b -> c) -> (a :* b) -> c instance GHC.Classes.Ord a => GHC.Classes.Ord (AsyncRattus.Strict.Maybe' a) instance GHC.Classes.Eq a => GHC.Classes.Eq (AsyncRattus.Strict.Maybe' a) instance GHC.Show.Show a => GHC.Show.Show (AsyncRattus.Strict.Maybe' a) instance Data.Traversable.Traversable AsyncRattus.Strict.List instance GHC.IsList.IsList (AsyncRattus.Strict.List a) instance Data.Foldable.Foldable AsyncRattus.Strict.List instance GHC.Base.Functor AsyncRattus.Strict.List instance GHC.Classes.Eq a => GHC.Classes.Eq (AsyncRattus.Strict.List a) instance GHC.Show.Show a => GHC.Show.Show (AsyncRattus.Strict.List a) instance GHC.Base.Functor ((AsyncRattus.Strict.:*) a) instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (a AsyncRattus.Strict.:* b) instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (a AsyncRattus.Strict.:* b) instance (Data.VectorSpace.VectorSpace v a, Data.VectorSpace.VectorSpace w a, GHC.Float.Floating a, GHC.Classes.Eq a) => Data.VectorSpace.VectorSpace (v AsyncRattus.Strict.:* w) a -- | This module is meant for library authors that want to build APIs for -- interacting with asynchronous resources, e.g. a GUI framework. module AsyncRattus.Channels -- | This function can be used to implement input signals. It returns a -- boxed delayed computation s and a callback function -- cb. The signal mkSig s will produce a new value -- v whenever the callback function cb is called with -- argument v. getInput :: IO (Box (O a) :* (a -> IO ())) -- | This function can be used to produces outputs. Given a signal -- s and function f, the call setOutput s f -- registers f as a callback function that is called with -- argument v whenever the signal produces a new value -- v. For this function to work, startEventLoop must be -- called. setOutput :: Producer p a => p -> (a -> IO ()) -> IO () -- | This function is essentially the composition of getInput and -- setOutput. It turns any producer into a signal. mkInput :: Producer p a => p -> IO (Box (O a)) -- | In order for setOutput to work, this IO action must be invoked. startEventLoop :: IO () -- | timer n produces a delayed computation that ticks every -- n milliseconds. In particular mkSig (timer n) is a -- signal that produces a new value every milliseconds. timer :: Int -> Box (O ()) -- | A type p satisfying Producer p a is essentially a -- signal that produces values of type a but it might not -- produce such values at each tick. class Producer p a | p -> a -- | Get the current value of the producer if any. getCurrent :: Producer p a => p -> Maybe' a -- | Get the next state of the producer. Morally, the type of this method -- should be -- --
-- getNext :: p -> (exists q. Producer q a => O q) ---- -- We encode the existential type using continuation-passing style. getNext :: Producer p a => p -> (forall q. Producer q a => O q -> b) -> b instance AsyncRattus.Channels.Producer p a => AsyncRattus.Channels.Producer (AsyncRattus.InternalPrimitives.O p) a instance AsyncRattus.Channels.Producer p a => AsyncRattus.Channels.Producer (AsyncRattus.InternalPrimitives.Box p) a -- | The bare-bones Asynchronous Rattus language. To program with streams, -- you can use AsyncRattus.Stream. module AsyncRattus -- | By default all Async Rattus functions are checked for use of lazy data -- types, since these may cause memory leaks. If any lazy data types are -- used, a warning is issued. These warnings can be disabled by -- annotating the module or the function with AllowLazyData -- --
-- {-# ANN myFunction AllowLazyData #-}
--
-- {-# ANN module AllowLazyData #-}
--
--
-- Async Rattus only allows guarded recursion, i.e. recursive calls must
-- occur in the scope of a tick. Structural recursion over strict data
-- types is safe as well, but is currently not checked. To disable the
-- guarded recursion check, annotate the module or function with
-- AllowRecursion.
--
--
-- {-# ANN myFunction AllowRecursion #-}
--
-- {-# ANN module AllowRecursion #-}
--
data AsyncRattus
AllowLazyData :: AsyncRattus
AllowRecursion :: AsyncRattus
mapO :: Box (a -> b) -> O a -> O b
-- | Programming with signals.
module AsyncRattus.Signal
-- | Sig a is a stream of values of type a.
data Sig a
(:::) :: !a -> !O (Sig a) -> Sig a
infixr 5 :::
-- | Apply a function to the value of a signal.
map :: Box (a -> b) -> Sig a -> Sig b
-- | Turn a producer into a signal. This is a variant of mkInput
-- that returns a signal instead of a boxed delayed computation.
mkInputSig :: Producer p a => p -> IO (Box (O (Sig a)))
-- | Variant of getInput that returns a signal instead of a boxed
-- delayed computation.
getInputSig :: IO (Box (O (Sig a)) :* (a -> IO ()))
-- | This function is essentially the composition of filter with
-- map. The signal produced by filterMap f s has the
-- value v whenever s has the value u such
-- that unbox f u = Just' v.
filterMap :: Box (a -> Maybe' b) -> Sig a -> IO (Box (O (Sig b)))
-- | This function is similar to filterMap but takes a delayed
-- signal (type O (Sig a)) as an argument instead of a signal
-- (Sig a).
filterMapAwait :: Box (a -> Maybe' b) -> O (Sig a) -> IO (Box (O (Sig b)))
-- | Filter the given signal using a predicate. The signal produced by
-- filter p s contains only values from s that satisfy
-- the predicate p.
filter :: Box (a -> Bool) -> Sig a -> IO (Box (O (Sig a)))
-- | This function is similar to filter but takes a delayed signal
-- (type O (Sig a)) as an argument instead of a signal (Sig
-- a).
filterAwait :: Box (a -> Bool) -> O (Sig a) -> IO (Box (O (Sig a)))
-- | This function is a variant of zipWith. Whereas zipWith f xs
-- ys produces a new value whenever xs or ys
-- produce a new value, trigger f xs ys only produces a new
-- value when xs produces a new value.
--
-- Example:
--
-- -- xs: 1 0 5 2 -- ys: 1 2 3 2 -- -- zipWith (box (+)) xs ys: 2 3 4 3 8 4 -- trigger (box (+)) xy ys: 2 3 8 4 --trigger :: (Stable a, Stable b) => Box (a -> b -> c) -> Sig a -> Sig b -> IO (Box (Sig c)) -- | This function is similar to trigger but takes a delayed signal -- (type O (Sig a)) as an argument instead of a signal (Sig -- a). -- -- Example: -- --
-- xs: 1 0 5 2 -- ys: 1 2 3 2 -- -- trigger (box (+)) xy ys: 2 3 8 4 --triggerAwait :: Stable b => Box (a -> b -> c) -> O (Sig a) -> Sig b -> IO (Box (O (Sig c))) -- | A version of map for delayed signals. mapAwait :: Box (a -> b) -> O (Sig a) -> O (Sig b) -- | This function allows to switch from one signal to another one -- dynamically. The signal defined by switch xs ys first behaves -- like xs, but as soon as ys produces a new value, -- switch xs ys behaves like ys. -- -- Example: -- --
-- xs: 1 2 3 4 5 6 7 8 9 -- ys: 1 2 3 4 5 6 -- -- switch xs ys: 1 2 3 1 2 3 4 5 6 --switch :: Sig a -> O (Sig a) -> Sig a -- | This function is similar to switch, but the (future) second -- signal may depend on the last value of the first signal. switchS :: Stable a => Sig a -> O (a -> Sig a) -> Sig a -- | This function is similar to switch but works on delayed signals -- instead of signals. switchAwait :: O (Sig a) -> O (Sig a) -> O (Sig a) -- | Variant of switchS that repeatedly switches. The output signal -- switch xs ys first behaves like xs, but whenever -- ys produces a value f, the signal switches to f -- v where v is the previous value of the output signal. -- -- switchS can be considered a special case of switchR that -- only makes a single switch. That is we have the following: -- --
-- switchS xs ys = switchR (delay (const (adv xs))) ys --switchR :: Stable a => Sig a -> O (Sig (a -> Sig a)) -> Sig a -- | This function interleaves two signals producing a new value v -- whenever either input stream produces a new value v. In case -- the input signals produce a new value simultaneously, the function -- argument is used break ties, i.e. to compute the new output value -- based on the two new input values -- -- Example: -- --
-- xs: 1 3 5 3 1 3 -- ys: 0 2 4 -- -- interleave (box (+)) xs ys: 1 3 2 5 7 1 3 --interleave :: Box (a -> a -> a) -> O (Sig a) -> O (Sig a) -> O (Sig a) -- | This is the composition of mapAwait and interleave. That -- is, -- --
-- mapInterleave f g xs ys = mapAwait f (interleave xs ys) --mapInterleave :: Box (a -> a) -> Box (a -> a -> a) -> O (Sig a) -> O (Sig a) -> O (Sig a) interleaveAll :: Box (a -> a -> a) -> List (O (Sig a)) -> O (Sig a) -- | Takes two signals and updates the first signal using the functions -- produced by the second signal: -- -- Law: -- --
-- (xs `update` fs) `update` gs = (xs `update` (interleave (box (.)) gs fs)) --update :: Stable a => Sig a -> O (Sig (a -> a)) -> Sig a -- | Turns a boxed delayed computation into a delayed signal. mkSig :: Box (O a) -> O (Sig a) -- | Variant of mkSig that returns a boxed delayed signal mkBoxSig :: Box (O a) -> Box (O (Sig a)) -- | Get the current value of a signal. current :: Sig a -> a -- | Get the future the signal. future :: Sig a -> O (Sig a) -- | Construct a constant signal that never updates. const :: a -> Sig a -- | Similar to Haskell's scanl. -- --
-- scan (box f) x (v1 ::: v2 ::: v3 ::: ... ) == (x `f` v1) ::: ((x `f` v1) `f` v2) ::: ... ---- -- Note: Unlike scanl, scan starts with x f -- v1, not x. scan :: Stable b => Box (b -> a -> b) -> b -> Sig a -> Sig b -- | Like scan, but uses a delayed signal. scanAwait :: Stable b => Box (b -> a -> b) -> b -> O (Sig a) -> Sig b -- | scanMap is a composition of map and scan: -- --
-- scanMap f g x === map g . scan f x --scanMap :: Stable b => Box (b -> a -> b) -> Box (b -> c) -> b -> Sig a -> Sig c -- | jump (box f) xs first behaves like xs, but as soon -- as f x = Just xs' for a (current or future) value x -- of xs, it behaves like xs'. jump :: Box (a -> Maybe' (Sig a)) -> Sig a -> Sig a -- | Similar to jump, but it can jump repeatedly. That is, -- jumping (box f) xs first behaves like xs, but every -- time f x = Just xs' for a (current or future) value -- x of jumping (box f) xs, it behaves like -- xs'. jumping :: Box (a -> Maybe' (Sig a)) -> Sig a -> Sig a -- | Stops as soon as the the predicate becomes true for the current value. -- That is, stop (box p) xs first behaves as xs, but as -- soon as f x = True for some (current or future) value -- x of xs, then it behaves as const x. stop :: Box (a -> Bool) -> Sig a -> Sig a -- | This function is a variant of combines the values of two signals using -- the function argument. zipWith f xs ys produces a new value -- unbox f x y whenever xs or ys produce a new -- value, where x and y are the current values of -- xs and ys, respectively. -- -- Example: -- --
-- xs: 1 2 3 2 -- ys: 1 0 5 2 -- -- zipWith (box (+)) xs ys: 2 3 4 3 8 4 --zipWith :: (Stable a, Stable b) => Box (a -> b -> c) -> Sig a -> Sig b -> Sig c -- | Variant of zipWith with three signals. zipWith3 :: forall a b c d. (Stable a, Stable b, Stable c) => Box (a -> b -> c -> d) -> Sig a -> Sig b -> Sig c -> Sig d -- | This is a special case of zipWith using the tupling function. -- That is, -- --
-- zip = zipWith (box (:*)) --zip :: (Stable a, Stable b) => Sig a -> Sig b -> Sig (a :* b) -- | This is a variant of zipWith, but the values passed to the -- function may not exist if the corresponding source signal has not -- ticked. -- -- Example: -- --
-- xs: 1 2 3 -- ys: 1 0 5 -- -- parallelWith (box (:*)) xs ys: (J 1 :* J 1) (J 2 :* N) (J 3 :* J 0) (N :* J 5) --parallelWith :: Box (Maybe' a -> Maybe' b -> c) -> Sig a -> Sig b -> Sig c -- | This is a variant of parallelWith for delayed signals. -- -- Example: -- --
-- xs: 2 3 -- ys: 0 5 -- -- paralle (box (:*)) xs ys: (J 2 :* N) (J 3 :* J 0) (N :* J 5) --parallelWithAwait :: Box (Maybe' a -> Maybe' b -> c) -> O (Sig a) -> O (Sig b) -> O (Sig c) -- | This is a variant of zip, but the signal of pairs only contain -- values if the corresponding source signal ticked. -- -- Example: -- --
-- xs: 1 2 3 -- ys: 1 0 5 -- -- parallel xs ys: (J 1 :* J 1) (J 2 :* N) (J 3 :* J 0) (N :* J 5) --parallel :: Sig a -> Sig b -> Sig (Maybe' a :* Maybe' b) -- | This is a variant of parallel for delayed signals. -- -- Example: -- --
-- xs: 2 3 -- ys: 0 5 -- -- parallel xs ys: (J 2 :* N) (J 3 :* J 0) (N :* J 5) --parallelAwait :: O (Sig a) -> O (Sig b) -> O (Sig (Maybe' a :* Maybe' b)) -- | If-then-else lifted to signals. cond bs xs ys produces a -- stream whose value is taken from xs whenever bs is -- true and from ys otherwise. cond :: Stable a => Sig Bool -> Sig a -> Sig a -> Sig a buffer :: Stable a => a -> Sig a -> Sig a bufferAwait :: Stable a => a -> O (Sig a) -> O (Sig a) -- | integral x xs computes the integral of the signal xs -- with the constant x. For example, if xs is the -- velocity of an object, the signal integral 0 xs describes the -- distance travelled by that object. integral :: forall a v. (VectorSpace v a, Eq v, Fractional a, Stable v, Stable a) => v -> Sig v -> Sig v -- | Compute the derivative of a signal. For example, if xs is the -- velocity of an object, the signal derivative xs describes the -- acceleration travelled by that object. derivative :: forall a v. (VectorSpace v a, Eq v, Fractional a, Stable v, Stable a) => Sig v -> Sig v instance AsyncRattus.Channels.Producer (AsyncRattus.Signal.SigMaybe a) a instance AsyncRattus.Channels.Producer (AsyncRattus.Signal.Sig a) a -- | Programming with futures. module AsyncRattus.Future -- | F a will produces a value of type a after zero or -- more ticks of some clocks data F a Now :: !a -> F a Wait :: !O (F a) -> F a -- | SigF a is a signal of values of type a. In contrast -- to Sig, SigF supports the filter and -- filterMap functions. data SigF a (:>:) :: !a -> !O (F (SigF a)) -> SigF a mkSigF :: Box (O a) -> F (SigF a) mkSigF' :: Box (O a) -> O (F (SigF a)) -- | Get the current value of a signal. current :: SigF a -> a -- | Get the future the signal. future :: SigF a -> O (F (SigF a)) bindF :: F a -> Box (a -> F b) -> F b mapF :: Box (a -> b) -> F a -> F b sync :: O (F a) -> O (F b) -> O (F a :* F b) syncF :: (Stable a, Stable b) => F a -> F b -> F (a :* b) switchAwait :: F (SigF a) -> F (SigF a) -> F (SigF a) switch :: SigF a -> F (SigF a) -> SigF a switchS :: Stable a => SigF a -> F (a -> SigF a) -> SigF a filterMap :: Box (a -> Maybe' b) -> SigF a -> F (SigF b) filterMapAwait :: Box (a -> Maybe' b) -> F (SigF a) -> F (SigF b) filterAwait :: Box (a -> Bool) -> F (SigF a) -> F (SigF a) filter :: Box (a -> Bool) -> SigF a -> F (SigF a) trigger :: Stable b => Box (a -> b -> c) -> SigF a -> SigF b -> SigF c triggerAwait :: Stable b => Box (a -> b -> c) -> F (SigF a) -> SigF b -> F (SigF c) map :: Box (a -> b) -> SigF a -> SigF b mapAwait :: Box (a -> b) -> F (SigF a) -> F (SigF b) zipWith :: (Stable a, Stable b) => Box (a -> b -> c) -> SigF a -> SigF b -> SigF c zipWithAwait :: (Stable a, Stable b) => Box (a -> b -> c) -> a -> b -> F (SigF a) -> F (SigF b) -> F (SigF c) fromSig :: Sig a -> SigF a scan :: Stable b => Box (b -> a -> b) -> b -> SigF a -> SigF b scanAwait :: Stable b => Box (b -> a -> b) -> b -> F (SigF a) -> F (SigF b) instance AsyncRattus.Channels.Producer (AsyncRattus.Future.SigF a) a instance AsyncRattus.Channels.Producer (AsyncRattus.Future.OneShot a) a instance AsyncRattus.Channels.Producer p a => AsyncRattus.Channels.Producer (AsyncRattus.Future.F p) a