aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/world
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/library/lux/world/net/http/response.lux7
-rw-r--r--stdlib/source/library/lux/world/time/series.lux189
-rw-r--r--stdlib/source/library/lux/world/time/series/average.lux129
3 files changed, 230 insertions, 95 deletions
diff --git a/stdlib/source/library/lux/world/net/http/response.lux b/stdlib/source/library/lux/world/net/http/response.lux
index 1c8cef67c..93bd80ac8 100644
--- a/stdlib/source/library/lux/world/net/http/response.lux
+++ b/stdlib/source/library/lux/world/net/http/response.lux
@@ -13,9 +13,10 @@
[encoding
["[0]" utf8]]]
[format
- ["[0]" html]
- ["[0]" css (.only CSS)]
- ["[0]" json (.only JSON) (.use "[1]#[0]" codec)]]]]]
+ ["[0]" json (.only JSON) (.use "[1]#[0]" codec)]]]
+ [web
+ ["[0]" html]
+ ["[0]" css (.only CSS)]]]]
["[0]" // (.only Body Message)
["[0]" status (.only Status)]
["[0]" header]
diff --git a/stdlib/source/library/lux/world/time/series.lux b/stdlib/source/library/lux/world/time/series.lux
index c529f6636..debbe884a 100644
--- a/stdlib/source/library/lux/world/time/series.lux
+++ b/stdlib/source/library/lux/world/time/series.lux
@@ -4,121 +4,126 @@
[abstract
[equivalence (.only Equivalence)]
[functor (.only Functor)]
- [mix (.only Mix)]]
+ [mix (.only Mix)]
+ [monad (.only do)]]
[control
["[0]" try (.only Try)]
["[0]" exception (.only Exception)]]
[data
+ ["[0]" product]
[text
["%" \\format]]
[collection
- ["[0]" array (.only Array) (.use "[1]#[0]" functor mix)
- ["/" \\unsafe]]]]
+ ["/" sequence (.use "[1]#[0]" functor mix)]]]
+ [math
+ [number
+ ["n" nat]]]
[meta
- [type
- ["[0]" nominal]]]]]
+ [type (.only sharing)]]]]
[//
+ ["[0]" duration (.only Duration) (.use "[1]#[0]" equivalence)]
["[0]" instant (.only Instant) (.use "[1]#[0]" order)]])
-(type .public (Event of)
+(type .public (Series of)
(Record
- [#when Instant
- #what of]))
+ [#start Instant
+ #interval Duration
+ #data (/.Sequence of)]))
-(def (event_equivalence super)
+(def .public (equivalence super)
(All (_ of)
(-> (Equivalence of)
- (Equivalence (Event of))))
+ (Equivalence (Series of))))
+ (all product.equivalence
+ instant.equivalence
+ duration.equivalence
+ (/.equivalence super)
+ ))
+
+(def .public functor
+ (Functor Series)
(implementation
- (def (= reference example)
- (and (instant#= (the #when reference) (the #when example))
- (of super = (the #what reference) (the #what example))))))
+ (def (each $)
+ (|>> (revised #data (/#each $))))))
-(nominal.def .public (Series of)
- (Array (Event of))
+(def .public mix
+ (Mix Series)
+ (implementation
+ (def (mix $ init)
+ (|>> (the #data)
+ (/#mix $ init)))))
- (def .public (equivalence super)
- (All (_ of)
- (-> (Equivalence of)
- (Equivalence (Series of))))
- (implementation
- (def (= reference example)
- (of (array.equivalence (event_equivalence super)) =
- (nominal.representation reference)
- (nominal.representation example)))))
+(def .public size
+ (All (_ of)
+ (-> (Series of)
+ Nat))
+ (|>> (the #data)
+ /.size))
- (def .public functor
- (Functor Series)
- (implementation
- (def (each $)
- (|>> nominal.representation
- (array#each (revised #what $))
- nominal.abstraction))))
+(def .public start
+ (All (_ of)
+ (-> (Series of)
+ Instant))
+ (the #start))
- (def .public mix
- (Mix Series)
- (implementation
- (def (mix $ init)
- (|>> nominal.representation
- (array#mix (function (_ next it)
- ($ (the #what next) it))
- init)))))
+(def .public (end it)
+ (All (_ of)
+ (-> (Series of)
+ Instant))
+ (instant.after (duration.up (-- (/.size (the #data it)))
+ (the #interval it))
+ (the #start it)))
- (exception.def .public (disordered [before after])
- (Exception [Instant Instant])
- (exception.report
- (list ["(Expected) before" (%.instant before)]
- ["(Expected) after" (%.instant after)])))
+(def .public (at event it)
+ (All (_ of)
+ (-> Nat (Series of)
+ Instant))
+ (instant.after (duration.up event (the #interval it))
+ (the #start it)))
- (exception.def .public (duplicated it)
- (Exception Instant)
- (exception.report
- (list ["Time-stamp" (%.instant it)])))
+(exception.def .public empty)
- (def .public (series it)
- (All (_ of)
- (-> (List (Event of))
- (Try (Series of))))
- (when it
- {.#Item head tail}
- (loop (again [previous head
- it tail])
- (when it
- {.#Item current next}
- (if (instant#< (the #when current) (the #when previous))
- (again current next)
- (if (instant#= (the #when current) (the #when previous))
- (exception.except ..duplicated [(the #when current)])
- (exception.except ..disordered [(the #when previous) (the #when current)])))
-
- {.#End}
- {try.#Success (nominal.abstraction
- (array.of_list it))}))
-
- {.#End}
- {try.#Success (nominal.abstraction
- (array.empty 0))}))
+(with_template [<index> <name>]
+ [(def .public (<name> it)
+ (All (_ of)
+ (-> (Series of)
+ (Try of)))
+ (let [data (the #data it)]
+ (when (/.size data)
+ 0 (exception.except ..empty [])
+ @ (/.item <index> data))))]
- (def .public size
- (All (_ of)
- (-> (Series of)
- Nat))
- (|>> nominal.representation
- /.size))
+ [(|> 0) earliest]
+ [(-- @) latest]
+ )
- (exception.def .public empty)
-
- (with_template [<name> <index>]
- [(def .public (<name> it)
- (All (_ of)
- (-> (Series of)
- (Try (Event of))))
- (let [it (nominal.representation it)]
- (when (array.size it)
- 0 (exception.except ..empty [])
- @ {try.#Success (/.item <index> it)})))]
+(exception.def .public (window_goes_out_of_bounds [offset size max_size])
+ (Exception [Nat Nat Nat])
+ (exception.report
+ (list ["From" (%.nat offset)]
+ ["To" (%.nat (n.+ offset size))]
+ ["Maximum" (%.nat max_size)])))
- [earliest 0]
- [latest (-- @)]
- )
- )
+(def .public (window offset size it)
+ (All (_ of)
+ (-> Nat Nat (Series of)
+ (Try (Series of))))
+ (if (n.< (n.+ offset size)
+ (..size it))
+ (exception.except ..window_goes_out_of_bounds [offset size (..size it)])
+ (let [input (the #data it)]
+ (loop (again [item 0
+ output (sharing [of]
+ (is (/.Sequence of)
+ input)
+ (is (/.Sequence of)
+ /.empty))])
+ (if (n.< size item)
+ (do try.monad
+ [it (/.item (n.+ offset item) input)]
+ (again (++ item) (/.suffix it output)))
+ {try.#Success (let [interval (the #interval it)]
+ [#start (instant.after (duration.up offset interval)
+ (the #start it))
+ #interval interval
+ #data output])})))))
diff --git a/stdlib/source/library/lux/world/time/series/average.lux b/stdlib/source/library/lux/world/time/series/average.lux
new file mode 100644
index 000000000..553cfee7f
--- /dev/null
+++ b/stdlib/source/library/lux/world/time/series/average.lux
@@ -0,0 +1,129 @@
+(.require
+ [library
+ [lux (.except)
+ [abstract
+ [monad (.only do)]]
+ [control
+ ["[0]" try (.only Try)]
+ ["[0]" exception (.only Exception)]]
+ [data
+ ["[0]" product]
+ [text
+ ["%" \\format]]
+ [collection
+ ["[0]" sequence (.only Sequence) (.use "[1]#[0]" mix functor)]]]
+ [math
+ [number
+ ["n" nat]
+ ["f" frac]]]
+ [meta
+ [type (.only sharing)]]]]
+ ["[0]" // (.only Series) (.use "[1]#[0]" mix)])
+
+... https://en.wikipedia.org/wiki/Moving_average#Cumulative_average
+(def .public cumulative
+ (-> (Series Frac)
+ (Series Frac))
+ (revised //.#data
+ (|>> (sequence#mix (function (_ event [[previous_summation previous_period] output])
+ (let [summation (f.+ previous_summation event)
+ average (f./ previous_period summation)]
+ [[summation (f.+ +1.0 previous_period)]
+ (sequence.suffix average output)]))
+ [[+0.0 +1.0] (is (Sequence Frac)
+ sequence.empty)])
+ product.right)))
+
+(exception.def .public (window_size_is_too_large [maximum actual])
+ (Exception [Nat Nat])
+ (exception.report
+ (list ["Maximum" (%.nat maximum)]
+ ["Actual" (%.nat actual)])))
+
+(def .public (windows size it)
+ (All (_ of)
+ (-> Nat (Series of)
+ (Try (Series (Series of)))))
+ (let [maximum (//.size it)]
+ (if (n.< size maximum)
+ (exception.except ..window_size_is_too_large [maximum size])
+ (let [limit (n.- size maximum)]
+ (loop (again [offset 0
+ output (sharing [of]
+ (is (Series of)
+ it)
+ (is (Sequence (Series of))
+ sequence.empty))])
+ (if (n.< limit offset)
+ (do try.monad
+ [current (//.window offset size it)]
+ (again (++ offset)
+ (sequence.suffix current output)))
+ {try.#Success (has //.#data output it)}))))))
+
+(type .public (Average of)
+ (-> (Series of)
+ of))
+
+... https://en.wikipedia.org/wiki/Moving_average
+(def .public (moving average additional it)
+ (All (_ of)
+ (-> (Average of) Nat (Series of)
+ (Try (Series of))))
+ (do try.monad
+ [.let [size (++ additional)]
+ it (windows size it)]
+ (in (|> it
+ (revised //.#data (sequence#each average))
+ (has //.#start (//.at size it))))))
+
+... https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
+... https://en.wikipedia.org/wiki/Exponential_smoothing
+(type .public Factor
+ (-> Nat
+ Frac))
+
+(def .public (simple_factor additional)
+ Factor
+ (f./ (n.frac (n.+ 2 additional))
+ +2.0))
+
+(def .public (exponential factor)
+ (-> Factor
+ (Average Frac))
+ (function (_ it)
+ (let [factor (factor (//.size it))
+ ~factor (f.- factor +1.0)]
+ (//#mix (is (-> Frac Frac
+ Frac)
+ (function (_ event previous)
+ (f.+ (f.* ~factor previous)
+ (f.* factor event))))
+ +0.0
+ it))))
+
+... https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average
+(def .public (simple it)
+ (Average Frac)
+ (|> (the //.#data it)
+ (sequence#mix f.+ +0.0)
+ (f./ (n.frac (//.size it)))))
+
+... https://en.wikipedia.org/wiki/Triangular_number
+(def (summation_up_to maximum)
+ (-> Nat
+ Nat)
+ (|> maximum
+ (n.* (++ maximum))
+ (n./ 2)))
+
+... https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average
+(def .public (weighted it)
+ (Average Frac)
+ (|> it
+ (//#mix (function (_ sample [weight summation])
+ [(f.+ +1.0 weight)
+ (|> sample (f.* weight) (f.+ summation))])
+ [+1.0 +0.0])
+ product.right
+ (f./ (n.frac (summation_up_to (-- (//.size it)))))))