2013-09-12 19:11:35 +00:00
|
|
|
module Signal where
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| The library for general signal manipulation. Includes lift functions up to
|
|
|
|
`lift8` and infix lift operators `<~` and `~`, combinations, filters, and
|
|
|
|
past-dependence.
|
|
|
|
|
2013-12-15 20:33:29 +00:00
|
|
|
Signals are time-varying values. Lifted functions are reevaluated whenever any of
|
2013-09-08 20:33:48 +00:00
|
|
|
their input signals has an event. Signal events may be of the same value as the
|
|
|
|
previous value of the signal. Such signals are useful for timing and
|
|
|
|
past-dependence.
|
|
|
|
|
|
|
|
Some useful functions for working with time (e.g. setting FPS) and combining
|
|
|
|
signals and time (e.g. delaying updates, getting timestamps) can be found in
|
|
|
|
the [`Time`](/docs/Signal/Time.elm) library.
|
|
|
|
|
|
|
|
# Combine
|
|
|
|
@docs constant, lift, lift2, merge, merges, combine
|
|
|
|
|
|
|
|
# Past-Dependence
|
|
|
|
@docs foldp, count, countIf
|
|
|
|
|
|
|
|
#Filters
|
|
|
|
@docs keepIf, dropIf, keepWhen, dropWhen, dropRepeats, sampleOn
|
|
|
|
|
2013-10-22 08:09:22 +00:00
|
|
|
# Pretty Lift
|
|
|
|
@docs (<~), (~)
|
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
# Do you even lift?
|
|
|
|
@docs lift3, lift4, lift5, lift6, lift7, lift8
|
|
|
|
|
|
|
|
-}
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-07-29 21:23:04 +00:00
|
|
|
import Native.Signal
|
2013-07-25 22:33:59 +00:00
|
|
|
import List (foldr)
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-07-29 13:47:48 +00:00
|
|
|
data Signal a = Signal
|
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Create a constant signal that never changes. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
constant : a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
constant = Native.Signal.constant
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Transform a signal with a given function. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
lift : (a -> b) -> Signal a -> Signal b
|
2013-07-29 21:23:04 +00:00
|
|
|
lift = Native.Signal.lift
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Combine two signals with a given function. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
lift2 : (a -> b -> c) -> Signal a -> Signal b -> Signal c
|
2013-07-29 21:23:04 +00:00
|
|
|
lift2 = Native.Signal.lift2
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-03-11 02:03:42 +00:00
|
|
|
lift3 : (a -> b -> c -> d) -> Signal a -> Signal b -> Signal c -> Signal d
|
2013-07-29 21:23:04 +00:00
|
|
|
lift3 = Native.Signal.lift3
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-03-11 02:03:42 +00:00
|
|
|
lift4 : (a -> b -> c -> d -> e) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e
|
2013-07-29 21:23:04 +00:00
|
|
|
lift4 = Native.Signal.lift4
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-03-11 02:03:42 +00:00
|
|
|
lift5 : (a -> b -> c -> d -> e -> f) -> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f
|
2013-07-29 21:23:04 +00:00
|
|
|
lift5 = Native.Signal.lift5
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-05-16 20:10:50 +00:00
|
|
|
lift6 : (a -> b -> c -> d -> e -> f -> g)
|
|
|
|
-> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g
|
2013-07-29 21:23:04 +00:00
|
|
|
lift6 = Native.Signal.lift6
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-05-16 20:10:50 +00:00
|
|
|
lift7 : (a -> b -> c -> d -> e -> f -> g -> h)
|
|
|
|
-> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h
|
2013-07-29 21:23:04 +00:00
|
|
|
lift7 = Native.Signal.lift7
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-05-16 20:10:50 +00:00
|
|
|
lift8 : (a -> b -> c -> d -> e -> f -> g -> h -> i)
|
|
|
|
-> Signal a -> Signal b -> Signal c -> Signal d -> Signal e -> Signal f -> Signal g -> Signal h -> Signal i
|
2013-07-29 21:23:04 +00:00
|
|
|
lift8 = Native.Signal.lift8
|
2013-07-25 22:33:59 +00:00
|
|
|
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Create a past-dependent signal. Each value given on the input signal will
|
|
|
|
be accumulated, producing a new output value.
|
|
|
|
|
|
|
|
For instance, `foldp (+) 0 (fps 40)` is the time the program has been running,
|
|
|
|
updated 40 times a second. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
foldp : (a -> b -> b) -> b -> Signal a -> Signal b
|
2013-07-29 21:23:04 +00:00
|
|
|
foldp = Native.Signal.foldp
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Merge two signals into one, biased towards the first signal if both signals
|
|
|
|
update at the same time. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
merge : Signal a -> Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
merge = Native.Signal.merge
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Merge many signals into one, biased towards the left-most signal if multiple
|
|
|
|
signals update simultaneously. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
merges : [Signal a] -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
merges = Native.Signal.merges
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Combine a list of signals into a signal of lists. -}
|
2013-04-03 16:54:10 +00:00
|
|
|
combine : [Signal a] -> Signal [a]
|
2013-07-29 21:23:04 +00:00
|
|
|
combine = foldr (Native.Signal.lift2 (::)) (Native.Signal.constant [])
|
2013-04-03 16:54:10 +00:00
|
|
|
|
2013-05-16 20:10:50 +00:00
|
|
|
-- Merge two signals into one, but distinguishing the values by marking the first
|
|
|
|
-- signal as `Left` and the second signal as `Right`. This allows you to easily
|
|
|
|
-- fold over non-homogeneous inputs.
|
|
|
|
-- mergeEither : Signal a -> Signal b -> Signal (Either a b)
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-12-17 23:44:45 +00:00
|
|
|
{-| Count the number of events that have occurred. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
count : Signal a -> Signal Int
|
2013-07-29 21:23:04 +00:00
|
|
|
count = Native.Signal.count
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-12-17 23:44:45 +00:00
|
|
|
{-| Count the number of events that have occurred that satisfy a given predicate.
|
2013-09-08 20:33:48 +00:00
|
|
|
-}
|
2013-03-11 02:03:42 +00:00
|
|
|
countIf : (a -> Bool) -> Signal a -> Signal Int
|
2013-07-29 21:23:04 +00:00
|
|
|
countIf = Native.Signal.countIf
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Keep only events that satisfy the given predicate. Elm does not allow
|
|
|
|
undefined signals, so a base case must be provided in case the predicate is
|
2014-01-20 06:40:24 +00:00
|
|
|
not satisfied initially. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
keepIf : (a -> Bool) -> a -> Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
keepIf = Native.Signal.keepIf
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Drop events that satisfy the given predicate. Elm does not allow undefined
|
2014-01-20 06:40:24 +00:00
|
|
|
signals, so a base case must be provided in case the predicate is satisfied
|
|
|
|
initially. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
dropIf : (a -> Bool) -> a -> Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
dropIf = Native.Signal.dropIf
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Keep events only when the first signal is true. When the first signal
|
|
|
|
becomes true, the most recent value of the second signal will be propagated.
|
|
|
|
Until the first signal becomes false again, all events will be propagated. Elm
|
|
|
|
does not allow undefined signals, so a base case must be provided in case the
|
2014-01-20 06:40:24 +00:00
|
|
|
first signal is not true initially. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
keepWhen : Signal Bool -> a -> Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
keepWhen = Native.Signal.keepWhen
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Drop events when the first signal is true. When the first signal becomes
|
|
|
|
false, the most recent value of the second signal will be propagated. Until the
|
|
|
|
first signal becomes true again, all events will be propagated. Elm does not
|
2014-01-20 06:40:24 +00:00
|
|
|
allow undefined signals, s oa base case must be provided in case the first
|
|
|
|
signal is true initially. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
dropWhen : Signal Bool -> a -> Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
dropWhen = Native.Signal.dropWhen
|
2013-03-24 12:45:56 +00:00
|
|
|
|
2014-01-20 15:48:43 +00:00
|
|
|
{-| Drop updates that repeat the current value of the signal.
|
|
|
|
|
|
|
|
Imagine a signal `numbers` has initial value
|
|
|
|
0 and then updates with values 0, 0, 1, 1, and 2. `dropRepeats numbers`
|
|
|
|
is a signal that has initial value 0 and updates as follows: ignore 0,
|
|
|
|
ignore 0, update to 1, ignore 1, update to 2. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
dropRepeats : Signal a -> Signal a
|
2013-07-29 21:23:04 +00:00
|
|
|
dropRepeats = Native.Signal.dropRepeats
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Sample from the second input every time an event occurs on the first input.
|
|
|
|
For example, `(sampleOn clicks (every second))` will give the approximate time
|
|
|
|
of the latest click. -}
|
2013-03-11 02:03:42 +00:00
|
|
|
sampleOn : Signal a -> Signal b -> Signal b
|
2013-07-29 21:23:04 +00:00
|
|
|
sampleOn = Native.Signal.sampleOn
|
2013-03-11 02:03:42 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| An alias for `lift`. A prettier way to apply a function to the current value
|
|
|
|
of a signal. -}
|
2013-04-03 16:54:10 +00:00
|
|
|
(<~) : (a -> b) -> Signal a -> Signal b
|
2013-07-29 21:23:04 +00:00
|
|
|
f <~ s = Native.Signal.lift f s
|
2013-04-03 16:54:10 +00:00
|
|
|
|
2013-09-08 20:33:48 +00:00
|
|
|
{-| Informally, an alias for `liftN`. Intersperse it between additional signal
|
|
|
|
arguments of the lifted function.
|
|
|
|
|
|
|
|
Formally, signal application. This takes two signals, holding a function and
|
|
|
|
a value. It applies the current function to the current value.
|
|
|
|
|
|
|
|
The following expressions are equivalent:
|
|
|
|
|
|
|
|
scene <~ Window.dimensions ~ Mouse.position
|
|
|
|
lift2 scene Window.dimensions Mouse.position
|
|
|
|
-}
|
2013-04-03 16:54:10 +00:00
|
|
|
(~) : Signal (a -> b) -> Signal a -> Signal b
|
2013-09-05 23:55:45 +00:00
|
|
|
sf ~ s = Native.Signal.lift2 (\f x -> f x) sf s
|
|
|
|
|
|
|
|
infixl 4 <~
|
2013-09-08 20:33:48 +00:00
|
|
|
infixl 4 ~
|