aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/type
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/library/lux/type.lux6
-rw-r--r--stdlib/source/library/lux/type/abstract.lux121
-rw-r--r--stdlib/source/library/lux/type/check.lux38
-rw-r--r--stdlib/source/library/lux/type/dynamic.lux4
-rw-r--r--stdlib/source/library/lux/type/implicit.lux13
-rw-r--r--stdlib/source/library/lux/type/quotient.lux16
-rw-r--r--stdlib/source/library/lux/type/refinement.lux24
-rw-r--r--stdlib/source/library/lux/type/resource.lux47
-rw-r--r--stdlib/source/library/lux/type/unit.lux89
-rw-r--r--stdlib/source/library/lux/type/variance.lux3
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))