diff options
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/library/lux/type.lux | 6 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/abstract.lux | 121 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/check.lux | 38 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/dynamic.lux | 4 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/implicit.lux | 13 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/quotient.lux | 16 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/refinement.lux | 24 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/resource.lux | 47 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/unit.lux | 89 | ||||
-rw-r--r-- | stdlib/source/library/lux/type/variance.lux | 3 |
10 files changed, 285 insertions, 76 deletions
diff --git a/stdlib/source/library/lux/type.lux b/stdlib/source/library/lux/type.lux index ed5964589..ba0384442 100644 --- a/stdlib/source/library/lux/type.lux +++ b/stdlib/source/library/lux/type.lux @@ -135,7 +135,7 @@ ($_ text\compose module "." name) )) -## https://en.wikipedia.org/wiki/Lambda_calculus#%CE%B2-reduction +... https://en.wikipedia.org/wiki/Lambda_calculus#%CE%B2-reduction (def: (reduced env type) (-> (List Type) Type Type) (case type @@ -180,7 +180,7 @@ (Equivalence Type) (def: (= x y) - (or (for {@.php false} ## TODO: Remove this once JPHP is gone. + (or (for {@.php false} ... TODO: Remove this once JPHP is gone. (is? x y)) (case [x y] [(#.Primitive xname xparams) (#.Primitive yname yparams)] @@ -439,7 +439,7 @@ (Parser Typed) (<>.and <code>.any <code>.any)) -## TODO: Make sure the generated code always gets optimized away. +... TODO: Make sure the generated code always gets optimized away. (syntax: .public (:sharing {type_vars ..type_parameters} {exemplar ..typed} {computation ..typed}) diff --git a/stdlib/source/library/lux/type/abstract.lux b/stdlib/source/library/lux/type/abstract.lux index 2ea87233e..79c5ecb41 100644 --- a/stdlib/source/library/lux/type/abstract.lux +++ b/stdlib/source/library/lux/type/abstract.lux @@ -19,7 +19,8 @@ [syntax (#+ syntax:) ["|.|" annotations]]]]]) -(type: Stack List) +(type: Stack + List) (def: peek (All [a] (-> (Stack a) (Maybe a))) @@ -34,6 +35,7 @@ list.tail) (type: .public Frame + {#.doc (doc "Meta-data about an abstract/nominal type in a stack of them.")} {#name Text #type_vars (List Code) #abstraction Code @@ -91,10 +93,12 @@ (exception.except ..no_active_frames []))))) (def: .public current + {#.doc (doc "The currently-being-defined abstract/nominal type.")} (Meta Frame) (..peek! #.None)) (def: .public (specific name) + {#.doc (doc "A specific abstract/nominal type still being defined somewhere in the scope.")} (-> Text (Meta Frame)) (..peek! (#.Some name))) @@ -175,6 +179,10 @@ (template [<name> <from> <to>] [(syntax: .public (<name> {[frame value] ..cast}) + {#.doc (doc "Type-casting macro for abstract/nominal types." + (: <to> + (<name> (: <from> + value))))} (do meta.monad [[name type_vars abstraction representation] (peek! frame)] (in (list (` ((~! :cast) [(~+ type_vars)] (~ <from>) (~ <to>) @@ -216,11 +224,89 @@ (<>.and (<>\in (` .private)) private) ))) -## TODO: Make sure the generated code always gets optimized away. -## (This applies to uses of ":abstraction" and ":representation") +... TODO: Make sure the generated code always gets optimized away. +... (This applies to uses of ":abstraction" and ":representation") (syntax: .public (abstract: {[export_policy [name type_vars] annotations representation_type primitives] ..abstract}) + {#.doc (doc "Define abstract/nominal types which hide their representation details." + "You can convert between the abstraction and its representation selectively to access the value, while hiding it from others." + (abstract: String + {#.doc "An opaque text."} + + Text + + (def: (string value) + (-> Text String) + (:abstraction value)) + + (def: (text value) + (-> String Text) + (:representation value))) + + "Type-parameters are optional." + (abstract: (Duplicate a) + {} + + [a a] + + (def: (duplicate value) + (All [a] (-> a (Duplicate a))) + (:abstraction [value value]))) + + "Definitions can be nested." + (abstract: (Single a) + {} + + a + + (def: (single value) + (All [a] (-> a (Single a))) + (:abstraction value)) + + (abstract: (Double a) + {} + + [a a] + + (def: (double value) + (All [a] (-> a (Double a))) + (:abstraction [value value])) + + (def: (single' value) + (All [a] (-> a (Single a))) + (:abstraction Single [value value])) + + (let [value 0123] + (is? value + (|> value + single' + (:representation Single) + double + :representation))))) + + "Type-parameters do not necessarily have to be used in the representation type." + "If they are not used, they become phantom types and can be used to customize types without changing the representation." + (abstract: (JavaScript a) + {} + + Text + + (abstract: Expression {} Any) + (abstract: Statement {} Any) + + (def: (+ x y) + (-> (JavaScript Expression) (JavaScript Expression) (JavaScript Expression)) + (:abstraction + (format "(" (:representation x) "+" (:representation y) ")"))) + + (def: (while test body) + (-> (JavaScript Expression) (JavaScript Statement) (JavaScript Statement)) + (:abstraction + (format "while(" (:representation test) ") {" + (:representation body) + "}")))) + )} (do meta.monad [current_module meta.current_module_name .let [type_varsC (list\map code.local_identifier type_vars) @@ -251,18 +337,39 @@ parser)) (syntax: .public (:transmutation {selection (..selection <code>.any)}) + {#.doc (doc "Transmutes an abstract/nominal type's phantom types." + (abstract: (JavaScript a) + {} + + Text + + (abstract: Expression {} Any) + (abstract: Statement {} Any) + + (def: (statement expression) + (-> (JavaScript Expression) (JavaScript Statement)) + (:transmutation expression)) + + (def: (statement' expression) + (-> (JavaScript Expression) (JavaScript Statement)) + (:transmutation JavaScript expression))))} (case selection (#Specific specific value) - (in (list (` (..:abstraction (~ specific) - (..:representation (~ specific) - (~ value)))))) + (in (list (` (.|> (~ value) + (..:representation (~ specific)) + (..:abstraction (~ specific)))))) (#Current value) - (in (list (` (..:abstraction (..:representation (~ value)))))))) + (in (list (` (.|> (~ value) ..:representation ..:abstraction)))))) (syntax: .public (^:representation {selection (<code>.form (..selection <code>.local_identifier))} body {branches (<>.some <code>.any)}) + {#.doc (doc "Pattern-matching macro to easily extract a representation." + (def: (computation abstraction) + (All [a] (-> (Abstract a) ???)) + (let [(^:representation value) abstraction] + (foo (bar (baz value))))))} (case selection (#Specific specific name) (let [g!var (code.local_identifier name)] diff --git a/stdlib/source/library/lux/type/check.lux b/stdlib/source/library/lux/type/check.lux index 352c5f3df..1c04d9482 100644 --- a/stdlib/source/library/lux/type/check.lux +++ b/stdlib/source/library/lux/type/check.lux @@ -53,12 +53,14 @@ ["Actual" (//.format actual)])) (type: .public Var + {#.doc (doc "The ID for a type-variable in a type-checking context.")} Nat) (type: Assumption [Type Type]) (type: .public (Check a) + {#.doc (doc "A type-checking computation which may fail or yield a value.")} (-> Type_Context (Try [Type_Context a]))) (type: (Checker a) @@ -183,7 +185,7 @@ (..failure (exception.error exception message))) (def: .public existential - {#.doc "A producer of existential types."} + {#.doc "A brand-new existential type."} (Check [Nat Type]) (function (_ context) (let [id (get@ #.ex_counter context)] @@ -234,6 +236,8 @@ (exception.except ..unknown_type_var id)))) (def: .public (bind type id) + {#.doc (doc "Attemmpts to buy a type-variable." + "Fails if the variable has been bound already.")} (-> Type Var (Check Any)) (function (_ context) (case (|> context (get@ #.var_bindings) (var::get id)) @@ -259,6 +263,7 @@ (exception.except ..unknown_type_var id)))) (def: .public var + {#.doc (doc "A brand-new (unbound) type-variable.")} (Check [Var Type]) (function (_ context) (let [id (get@ #.var_counter context)] @@ -300,7 +305,7 @@ Ring (set.empty n.hash)) -## TODO: Optimize this by not using sets anymore. +... TODO: Optimize this by not using sets anymore. (def: (ring start) (-> Var (Check Ring)) (function (_ context) @@ -324,6 +329,7 @@ (exception.except ..unknown_type_var current))))) (def: .public fresh_context + {#.doc (doc "An empty/un-used type-checking context.")} Type_Context {#.var_counter 0 #.ex_counter 0 @@ -360,7 +366,7 @@ (-> Assumption (List Assumption) (List Assumption)) (#.Item assumption assumptions)) -## TODO: "if_bind" can be optimized... +... TODO: "if_bind" can be optimized... (def: (if_bind id type then else) (All [a] (-> Var Type (Check a) (-> Type (Check a)) @@ -378,21 +384,21 @@ [?bound (read id)] (else (maybe.else (#.Var id) ?bound))))) -## TODO: "link_2" can be optimized... +... TODO: "link_2" can be optimized... (def: (link_2 left right) (-> Var Var (Check Any)) (do ..monad [_ (..bind (#.Var right) left)] (..bind (#.Var left) right))) -## TODO: "link_3" can be optimized... +... TODO: "link_3" can be optimized... (def: (link_3 interpose to from) (-> Var Var Var (Check Any)) (do ..monad [_ (update (#.Var interpose) from)] (update (#.Var to) interpose))) -## TODO: "check_vars" can be optimized... +... TODO: "check_vars" can be optimized... (def: (check_vars check' assumptions idE idA) (-> (Checker Type) (Checker Var)) (if (!n\= idE idA) @@ -401,13 +407,13 @@ [ebound (attempt (peek idE)) abound (attempt (peek idA))] (case [ebound abound] - ## Link the 2 variables circularly + ... Link the 2 variables circularly [#.None #.None] (do ! [_ (link_2 idE idA)] (in assumptions)) - ## Interpose new variable between 2 existing links + ... Interpose new variable between 2 existing links [(#.Some etype) #.None] (case etype (#.Var targetE) @@ -418,7 +424,7 @@ _ (check' assumptions etype (#.Var idA))) - ## Interpose new variable between 2 existing links + ... Interpose new variable between 2 existing links [#.None (#.Some atype)] (case atype (#.Var targetA) @@ -437,7 +443,7 @@ ringA (..ring idA)] (if (\ set.equivalence = ringE ringA) (in assumptions) - ## Fuse 2 rings + ... Fuse 2 rings (do ! [_ (monad.fold ! (function (_ interpose to) (do ! @@ -463,7 +469,7 @@ (All [a] (Check a)) (..failure "")) -## TODO: "check_apply" can be optimized... +... TODO: "check_apply" can be optimized... (def: (check_apply check' assumptions expected actual) (-> (Checker Type) (Checker [Type Type])) (let [[expected_input expected_function] expected @@ -554,11 +560,11 @@ (All [e a] (-> (Exception e) e (Check a) (Check a))) (|>> check (exception.with exception parameter))) -## TODO: "check'" can be optimized... +... TODO: "check'" can be optimized... (def: (check' assumptions expected actual) {#.doc "Type-check to ensure that the 'expected' type subsumes the 'actual' type."} (Checker Type) - (if (for {@.php false} ## TODO: Remove this once JPHP is gone. + (if (for {@.php false} ... TODO: Remove this once JPHP is gone. (is? expected actual)) (check\in assumptions) (with ..type_check_failed [expected actual] @@ -599,7 +605,7 @@ [actual' (apply_type! F A)] (check' assumptions expected actual')) - ## TODO: Refactor-away as cold-code + ... TODO: Refactor-away as cold-code (^template [<tag> <instancer>] [[(<tag> _) _] (do ..monad @@ -609,7 +615,7 @@ ([#.UnivQ ..existential] [#.ExQ ..var]) - ## TODO: Refactor-away as cold-code + ... TODO: Refactor-away as cold-code (^template [<tag> <instancer>] [[_ (<tag> _)] (do ..monad @@ -680,11 +686,13 @@ true)) (def: .public context + {#.doc (doc "The current state of the type-checking context.")} (Check Type_Context) (function (_ context) (#try.Success [context context]))) (def: .public (clean inputT) + {#.doc (doc "Resolves every bound type-variable to yield a new type that is as resolved as possible.")} (-> Type (Check Type)) (case inputT (#.Primitive name paramsT+) diff --git a/stdlib/source/library/lux/type/dynamic.lux b/stdlib/source/library/lux/type/dynamic.lux index bfd73455c..8b4780d1f 100644 --- a/stdlib/source/library/lux/type/dynamic.lux +++ b/stdlib/source/library/lux/type/dynamic.lux @@ -33,9 +33,9 @@ (in (list (` (let [(~ g!value) (~ value)] ((~! ..abstraction) [(:of (~ g!value)) (~ g!value)]))))))) - (syntax: .public (:check type value) + (syntax: .public (:static type value) {#.doc (doc (: (try.Try Nat) - (:check Nat (:dynamic 123))))} + (:static Nat (:dynamic 123))))} (with_gensyms [g!type g!value] (in (list (` (let [[(~ g!type) (~ g!value)] ((~! ..representation) (~ value))] (: ((~! try.Try) (~ type)) diff --git a/stdlib/source/library/lux/type/implicit.lux b/stdlib/source/library/lux/type/implicit.lux index b6b351262..74853320d 100644 --- a/stdlib/source/library/lux/type/implicit.lux +++ b/stdlib/source/library/lux/type/implicit.lux @@ -365,7 +365,7 @@ (#.Right [args _]) (do {! meta.monad} - [labels (|> (macro.gensym "") (list.repeat (list.size args)) (monad.seq !))] + [labels (|> (macro.gensym "") (list.repeated (list.size args)) (monad.seq !))] (in (list (` (let [(~+ (|> args (list.zipped/2 labels) (list\map ..pair_list) list\join))] (..\\ (~ (code.identifier member)) (~+ labels))))))) )) @@ -373,7 +373,7 @@ (def: (implicit_bindings amount) (-> Nat (Meta (List Code))) (|> (macro.gensym "g!implicit") - (list.repeat amount) + (list.repeated amount) (monad.seq meta.monad))) (def: implicits @@ -381,6 +381,10 @@ (<code>.tuple (<>.many <code>.any))) (syntax: .public (with {implementations ..implicits} body) + {#.doc (doc "Establish lexical bindings for implementations that will be prioritized over non-lexically-bound implementations." + (with [n.addition] + (n.= (\ n.addition compose left right) + (\\ compose left right))))} (do meta.monad [g!implicit+ (implicit_bindings (list.size implementations))] (in (list (` (let [(~+ (|> (list.zipped/2 g!implicit+ implementations) @@ -390,6 +394,11 @@ (~ body))))))) (syntax: .public (implicit: {implementations ..implicits}) + {#.doc (doc "Establish local definitions for implementations that will be prioritized over foreign definitions." + (implicit: [n.multiplication]) + + (n.= (\ n.multiplication compose left right) + (\\ compose left right)))} (do meta.monad [g!implicit+ (implicit_bindings (list.size implementations))] (in (|> (list.zipped/2 g!implicit+ implementations) diff --git a/stdlib/source/library/lux/type/quotient.lux b/stdlib/source/library/lux/type/quotient.lux index 5d2c29f2f..f68a1c099 100644 --- a/stdlib/source/library/lux/type/quotient.lux +++ b/stdlib/source/library/lux/type/quotient.lux @@ -9,7 +9,7 @@ abstract]]]) (abstract: .public (Class t c %) - {} + {#.doc (doc "The class knows how to classify/label values that are meant to be equivalent to one another.")} (-> t c) @@ -20,7 +20,9 @@ (|>> :abstraction)) (abstract: .public (Quotient t c %) - {} + {#.doc (doc "A quotient value has been labeled with a class." + "All equivalent values will belong to the same class." + "This means all equivalent values possess the same label.")} {#value t #label c} @@ -44,6 +46,16 @@ ) (syntax: .public (type class) + {#.doc (doc "The Quotient type associated with a Class type." + (def: even + (class even?)) + + (def: Even + Type + (type even)) + + (: Even + (quotient even 123)))} (with_gensyms [g!t g!c g!%] (in (list (` ((~! type.:by_example) [(~ g!t) (~ g!c) (~ g!%)] diff --git a/stdlib/source/library/lux/type/refinement.lux b/stdlib/source/library/lux/type/refinement.lux index a34153800..0ea7bf75c 100644 --- a/stdlib/source/library/lux/type/refinement.lux +++ b/stdlib/source/library/lux/type/refinement.lux @@ -9,15 +9,16 @@ abstract]]]) (abstract: .public (Refined t %) - {#.doc "A refined type '%' of base type 't' using a predicate."} + {#.doc "A refined version of another type, using a predicate to select valid instances."} {#value t #predicate (Predicate t)} (type: .public (Refiner t %) + {#.doc (doc "A selection mechanism for refined instances of a type.")} (-> t (Maybe (Refined t %)))) - (def: .public (refinement predicate) + (def: .public (refiner predicate) (All [t] (Ex [%] (-> (Predicate t) (Refiner t %)))) @@ -37,6 +38,8 @@ ) (def: .public (lift transform) + {#.doc (doc "Yields a function that can work on refined values." + "Respects the constraints of the refinement.")} (All [t %] (-> (-> t t) (-> (Refined t %) (Maybe (Refined t %))))) @@ -50,7 +53,8 @@ ) (def: .public (only refiner values) - (All [t %] (-> (Refiner t %) (List t) (List (Refined t %)))) + (All [t %] + (-> (Refiner t %) (List t) (List (Refined t %)))) (case values #.End #.End @@ -64,7 +68,9 @@ (only refiner tail)))) (def: .public (partition refiner values) - (All [t %] (-> (Refiner t %) (List t) [(List (Refined t %)) (List t)])) + {#.doc (doc "Separates refined values from the un-refined ones.")} + (All [t %] + (-> (Refiner t %) (List t) [(List (Refined t %)) (List t)])) (case values #.End [#.End #.End] @@ -81,6 +87,16 @@ (#.Item head no)])))) (syntax: .public (type refiner) + {#.doc (doc "The Refined type associated with a Refiner type." + (def: even + (refiner even?)) + + (def: Even + Type + (type even)) + + (: (Maybe Even) + (even 123)))} (macro.with_gensyms [g!t g!%] (in (list (` ((~! type.:by_example) [(~ g!t) (~ g!%)] (..Refiner (~ g!t) (~ g!%)) diff --git a/stdlib/source/library/lux/type/resource.lux b/stdlib/source/library/lux/type/resource.lux index 2a568e6fd..8d389b11e 100644 --- a/stdlib/source/library/lux/type/resource.lux +++ b/stdlib/source/library/lux/type/resource.lux @@ -26,17 +26,25 @@ abstract]]]) (type: .public (Procedure monad input output value) + {#.doc (doc "A computation that takes a sequence of resource access rights as inputs and yields a different sequence as outputs." + "A procedure yields a result value." + "A procedure can make use of monadic effects.")} (-> input (monad [output value]))) (type: .public (Linear monad value) + {#.doc (doc "A procedure that is constant with regards to resource access rights." + "This means no additional resources will be available after the computation is over." + "This also means no previously available resources will have been consumed.")} (All [keys] (Procedure monad keys keys value))) (type: .public (Affine monad permissions value) + {#.doc (doc "A procedure which expands the number of available resources.")} (All [keys] (Procedure monad keys [permissions keys] value))) (type: .public (Relevant monad permissions value) + {#.doc (doc "A procedure which reduces the number of available resources.")} (All [keys] (Procedure monad [permissions keys] keys value))) @@ -66,12 +74,17 @@ [output procedure] (in [keys output])))) -(abstract: .public Ordered {} Any) +(abstract: .public Ordered + {#.doc (doc "The mode of keys which CANNOT be swapped, and for whom order of release/consumption matters.")} + Any) -(abstract: .public Commutative {} Any) +(abstract: .public Commutative + {#.doc (doc "The mode of keys which CAN be swapped, and for whom order of release/consumption DOES NOT matters.")} + Any) (abstract: .public (Key mode key) - {} + {#.doc (doc "The access right for a resource." + "Without the key for a resource existing somewhere among the available ambient rights, one cannot use a resource.")} Any @@ -85,12 +98,14 @@ )) (abstract: .public (Res key value) - {#.doc "A value locked by a key."} + {#.doc (doc "A resource locked by a key." + "The 'key' represents the right to access/consume a resource.")} value (template [<name> <mode> <key>] [(def: .public (<name> monad value) + {#.doc (doc "Makes a value into a resource and adds the key/access-right to it to the ambient keyring for future use.")} (All [! v] (Ex [k] (-> (Monad !) v (Affine ! (Key <mode> k) (Res k v))))) (function (_ keys) (\ monad in [[(<key> []) keys] (:abstraction value)])))] @@ -100,6 +115,7 @@ ) (def: .public (read monad resource) + {#.doc (doc "Access the value of a resource, so long as its key is available.")} (All [! v k m] (-> (Monad !) (Res k v) (Relevant ! (Key m k) v))) (function (_ [key keys]) @@ -132,6 +148,16 @@ (\ monad in [context []]))) (syntax: .public (exchange {swaps ..indices}) + {#.doc (doc "A function that can exchange the keys for resource, so long as they are commutative." + "This keys will be placed at the front of the keyring in the order they are specified." + "The specific keys must be specified based of their index into the current keyring." + (do (..monad !) + [res|left (/.commutative ! pre) + res|right (/.commutative ! post) + _ ((/.exchange [1 0]) !) + left (/.read ! res|left) + right (/.read ! res|right)] + (in (format left right))))} (macro.with_gensyms [g!_ g!context g!!] (case swaps #.End @@ -140,7 +166,7 @@ (#.Item head tail) (do {! meta.monad} [.let [max_idx (list\fold n.max head tail)] - g!inputs (<| (monad.seq !) (list.repeat (inc max_idx)) (macro.gensym "input")) + g!inputs (<| (monad.seq !) (list.repeated (inc max_idx)) (macro.gensym "input")) .let [g!outputs (|> (monad.fold maybe.monad (function (_ from to) (do maybe.monad @@ -171,10 +197,19 @@ (template [<name> <from> <to>] [(syntax: .public (<name> {amount ..amount}) + {#.doc (doc "Group/un-group keys in the keyring into/out-of tuples." + (do (..monad !) + [res|left (/.commutative ! pre) + res|right (/.commutative ! post) + _ ((/.group 2) !) + _ ((/.un_group 2) !) + right (/.read ! res|right) + left (/.read ! res|left)] + (in (format left right))))} (macro.with_gensyms [g!_ g!context g!!] (do {! meta.monad} [g!keys (|> (macro.gensym "keys") - (list.repeat amount) + (list.repeated amount) (monad.seq !))] (in (list (` (: (All [(~ g!!) (~+ g!keys) (~ g!context)] (-> ((~! monad.Monad) (~ g!!)) diff --git a/stdlib/source/library/lux/type/unit.lux b/stdlib/source/library/lux/type/unit.lux index 3348ded53..35d0c66c8 100644 --- a/stdlib/source/library/lux/type/unit.lux +++ b/stdlib/source/library/lux/type/unit.lux @@ -11,11 +11,13 @@ ["<>" parser ("#\." monad) ["<.>" code (#+ Parser)]]] [data - [text + ["." text ["%" format (#+ format)]]] [macro ["." code] + ["." template] [syntax (#+ syntax:) + ["|.|" export] ["|.|" annotations]]] [math [number @@ -26,7 +28,7 @@ abstract]]]) (abstract: .public (Qty unit) - {} + {#.doc (doc "A quantity with an associated unit of measurement.")} Int @@ -60,12 +62,14 @@ ) (interface: .public (Unit a) + {#.doc (doc "A unit of measurement, to qualify numbers with.")} (: (-> Int (Qty a)) in) (: (-> (Qty a) Int) out)) (interface: .public (Scale s) + {#.doc (doc "A scale of magnitude.")} (: (All [u] (-> (Qty u) (Qty (s u)))) scale) (: (All [u] (-> (Qty (s u)) (Qty u))) @@ -74,6 +78,7 @@ ratio)) (type: .public Pure + {#.doc (doc "A pure, unit-less quantity.")} (Qty Any)) (def: .public pure @@ -84,17 +89,16 @@ (-> Pure Int) ..out) -(def: unitP - (Parser [Code Text Text |annotations|.Annotations]) - (let [private ($_ <>.and - <code>.local_identifier - <code>.local_identifier - (<>.else |annotations|.empty |annotations|.parser))] - (<>.either (<>.and <code>.any private) - (<>.and (<>\in (` .private)) private)))) - -(syntax: .public (unit: - {[export_policy type_name unit_name annotations] ..unitP}) +(syntax: .public (unit: {[export_policy type_name unit_name annotations] + (|export|.parser + ($_ <>.and + <code>.local_identifier + <code>.local_identifier + (<>.else |annotations|.empty |annotations|.parser)))}) + {#.doc (doc "Define a unit of measurement." + "Both the name of the type, and the name of the Unit implementation must be specified." + (unit: .public Feet feet + {#.doc (doc "Optional annotations.")}))} (do meta.monad [@ meta.current_module_name .let [g!type (code.local_identifier type_name)]] @@ -120,18 +124,17 @@ (n.> 0 denominator))] (in [numerator denominator])))) -(def: scaleP - (Parser [Code Text Text Ratio |annotations|.Annotations]) - (let [private ($_ <>.and - <code>.local_identifier - <code>.local_identifier - ..scale - (<>.else |annotations|.empty |annotations|.parser))] - (<>.either (<>.and <code>.any private) - (<>.and (<>\in (` .private)) private)))) - -(syntax: .public (scale: - {[export_policy type_name scale_name ratio annotations] ..scaleP}) +(syntax: .public (scale: {[export_policy type_name scale_name ratio annotations] + (|export|.parser + ($_ <>.and + <code>.local_identifier + <code>.local_identifier + ..scale + (<>.else |annotations|.empty |annotations|.parser)))}) + {#.doc (doc "Define a scale of magnitude." + (scale: .public Bajillion bajillion + [1 1,234,567,890] + {#.doc (doc "Optional annotations.")}))} (do meta.monad [.let [(^slots [#ratio.numerator #ratio.denominator]) ratio] @ meta.current_module_name @@ -167,18 +170,34 @@ (i./ (.int denominator)) in))) -(scale: .public Kilo kilo [1 1,000]) -(scale: .public Mega mega [1 1,000,000]) -(scale: .public Giga giga [1 1,000,000,000]) +(syntax: (implementation_name {type_name <code>.local_identifier}) + (in (list (code.local_identifier (text.lower_cased type_name))))) -(scale: .public Milli milli [ 1,000 1]) -(scale: .public Micro micro [ 1,000,000 1]) -(scale: .public Nano nano [1,000,000,000 1]) +(template [<type> <from> <to>] + [(`` (scale: .public <type> + (~~ (implementation_name <type>)) + [<from> <to>] + {#.doc (doc (~~ (template.text ["'" <type> "' scale from " <from> " to " <to> "."])))}))] -(unit: .public Gram gram) -(unit: .public Meter meter) -(unit: .public Litre litre) -(unit: .public Second second) + [Kilo 1 1,000] + [Mega 1 1,000,000] + [Giga 1 1,000,000,000] + + [Milli 1,000 1] + [Micro 1,000,000 1] + [Nano 1,000,000,000 1] + ) + +(template [<type>] + [(`` (unit: .public <type> + (~~ (implementation_name <type>)) + {#.doc (doc (~~ (template.text ["'" <type> "' unit of meaurement."])))}))] + + [Gram] + [Meter] + [Litre] + [Second] + ) (implementation: .public equivalence (All [unit] (Equivalence (Qty unit))) diff --git a/stdlib/source/library/lux/type/variance.lux b/stdlib/source/library/lux/type/variance.lux index 2a7d65267..8755777b9 100644 --- a/stdlib/source/library/lux/type/variance.lux +++ b/stdlib/source/library/lux/type/variance.lux @@ -3,10 +3,13 @@ [lux #*]]) (type: .public (Co t) + {#.doc (doc "A constraint for covariant types.")} (-> Any t)) (type: .public (Contra t) + {#.doc (doc "A constraint for contravariant types.")} (-> t Any)) (type: .public (In t) + {#.doc (doc "A constraint for invariant types.")} (-> t t)) |